Merge branch 'zynaddsubfx-master'

* zynaddsubfx-master: (28 commits)
  ZynAddSubFX: explicitely link RemoteZynAddSubFx.exe against Core library
  Revert "ZynAddSubFX/FLTK: updated to SVN revision 6909"
  Style: Restylized entire codebase
  SUBnote: integrated memcpy/memset
  ADnote: started to use memset/memcpy
  ADnote: Documented/added const usage
  OSS: Added failsafe based upon Jrmie Andri patch
  Unison improvements
  Bandwidth effect on Reverb
  Started to rewrite the Reverb's Bandwidth effect (based on a better idea)
  ZynAddSubFX/FLTK: updated to SVN revision 6909
  Merge branch 'master' into newXML
  ZynAddSubFX: rebuilt UI files with non-buggy Fluid
  ZynAddSubFX: rebuilt source files from UI files
  Merge branch 'master' of ssh://zynaddsubfx.git.sourceforge.net/gitroot/zynaddsubfx/zynaddsubfx
  Started to implement Bandwidth to the Reverb effect.
  Small enhancements and bugfixes to Unison
  Made unison vibratto LFO smoother
  Other improvements and bugfixes on Unison.
  Bugfixes
  ...
This commit is contained in:
Tobias Doerffel
2009-10-27 10:19:26 +01:00
153 changed files with 16455 additions and 13003 deletions

View File

@@ -11,6 +11,8 @@ Contributors:
Daniel Clemente (with a workaround of X11 repeated key bug)
Emmanuel Saracco (fix for JACK output)
Achim Settelmeier (QUERTZ keyboard layout for virtual keyboard)
Jérémie Andréi (AZERTY keyboard layout, Array index fix)
Jérémie Andréi (AZERTY keyboard layout, Array index fix, OSS failsafe)
Alexis Ballier (const char* <-> string mismatch, NULLMidi prototype fix)
Tobias Doerffel (static vs instance variables alteration)
James Morris (Memory leaks in FLTK GUI)

View File

@@ -53,7 +53,7 @@ IF(LMMS_HOST_X86 OR LMMS_HOST_X86_64)
ENDIF(LMMS_HOST_X86 OR LMMS_HOST_X86_64)
# build ZynAddSubFX with full optimizations
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wno-write-strings -Wno-deprecated-declarations")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-write-strings -Wno-deprecated-declarations")
# link system-libraries when on win32
IF(LMMS_BUILD_WIN32)
@@ -106,7 +106,8 @@ SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp ${ZYN_SRC_GUI})
INSTALL(TARGETS RemoteZynAddSubFx RUNTIME DESTINATION ${PLUGIN_DIR})
TARGET_LINK_LIBRARIES(RemoteZynAddSubFx ZynAddSubFxCore ${CMAKE_CURRENT_BINARY_DIR}/fltk/bin/libfltk.a)
TARGET_LINK_LIBRARIES(RemoteZynAddSubFx -L${CMAKE_CURRENT_BINARY_DIR} -lZynAddSubFxCore ${CMAKE_CURRENT_BINARY_DIR}/fltk/bin/libfltk.a)
ADD_DEPENDENCIES(RemoteZynAddSubFx ZynAddSubFxCore)
# link system libraries when on win32
IF(LMMS_BUILD_WIN32)

View File

@@ -1,4 +1,4 @@
6 Mar 2002 -(dupamasa - in jur de ora 4) Mi-a venit ideea exact cum sa fac cand ma plimbam pe strada Rolirudnap
6 Mar 2002 -(dupamasa - in jur de ora 4) Mi-a venit ideea exact cum sa fac cand ma plimbam pe strada Pandurilor
7/8 Mar 2002 - Started to do diagrams
10 Mar 2002 - Started to write "voice"
11 Mar 2002 - Heard first sound
@@ -892,3 +892,68 @@
07 Sep 2009 (Mark McCurry)
- Fixed glitch in XMLwrapper, which would prevent file loading
11 Sep 2009 (Mark McCurry)
- Moved PADsynth_used from public struct to has/set methods in
XMLwrapper
- Created wrapper functions, so that XMLwrapper can be somewhat
usable when const
- Removed multiple addparam methods and replaced it with one
variable argument function
- Replaced int2str, real2str, str2int, and str2real from XMLwrapper
with stringTo<T> and stringFrom<T> function templates in Util.
- Moved newFFTFREQS and deleteFFTFREQS from Util to FFTwrapper
- Removed unneeded stack from XMLwrapper
18 Sep 2009 (Mark McCurry)
- Started to use versioning information in XMLwrapper
- Remove last of stack helper functions in XMLwrapper
- Added std::string retreval to XMLwrapper
20 Sep 2009 (Paul Nasca)
- Started to implement the Unison effect for ADsynth
22 Sep 2009 (Paul Nasca)
- Added vibratto and other features to Unison effect
22 Sep 2009 (Mark McCurry)
- Changed temporary data for Oscilgen from static to instance
recommended by Tobias Doerffel
- Fixed Memory leaks in UI based upon James Morris' patch
23 Sep 2009 (Paul Nasca)
- Added unison invert phase
- Made unison frequency spread to depend on Bandwidth controllers and parameters
- Added unison vibratto speed control and other improvements
- bugfixes: Voice Amplitude Envelope and FM
24 Sep 2009 (Paul Nasca)
- Small enhancements and bugfixes to Unison
- Started to implement Bandwidth to the Reverb effect
25 Sep 2009 (Mark McCurry)
- Allowed for XMLwrapper to retrieve strings stored in mxml TEXT
fields
29 Sep 2009 (Paul Nasca)
- Remove the old (FFT based) Bandwidth effect to Reverb and started rewrite it (based on multivoice chorus/unison effect)
01 Oct 2009 (Paul Nasca)
- Corrected the ADsynth unison LFO rounding function
- Made Unison based on Bandwidth (in cents) parameter
02 Oct 2009 (Mark McCurry)
- Added OSS failsafe by Jérémie Andréi
04 Oct 2009 (Mark McCurry)
- fixed Ctest issues
06 Oct 2009 (Mark McCurry)
- Added first simple profiling test
08 Oct 2009 (Mark McCurry)
- Started to see if memset/memcpy offer performance benifits when
widely used
- Added basic SUBnote test
09 Oct 2009 (Mark McCurry)
- Restylized codebase with uncrustify

View File

@@ -22,19 +22,19 @@
#include "Control.h"
Control::Control(char ndefaultval)
:defaultval(ndefaultval),lockqueue(-1),locked(false)
:defaultval(ndefaultval), lockqueue(-1), locked(false)
{}
void Control::lock()
{
locked=true;
lockqueue=-1;
locked = true;
lockqueue = -1;
}
void Control::ulock()
{
if (locked&&lockqueue>=0)
if(locked && (lockqueue >= 0))
setmVal(lockqueue);
locked=false;
locked = false;
}

View File

@@ -25,33 +25,33 @@
/**A control for a parameter within the program*/
class Control
{
public:
Control(char ndefaultval);/**\todo create proper initialization list*/
~Control() {};
/**Return the string, which represents the internal value
* @return a string representation of the current value*/
virtual std::string getString()const=0;
/**Set the Control to the given value
* @param nval A number 0-127*/
virtual void setmVal(char nval)=0;
/**Return the midi value (aka the char)
* @return the current value*/
virtual char getmVal()const=0;
/** Will lock the Control until it is ulocked
*
* Locking a Control will Stop it from having
* its internal data altered*/
void lock();
/** Will unlock the Control
*
* This will also update the Control
* if something attempted to update it while it was locked*/
void ulock();
private:
char defaultval;/**<Default value of the Control*/
char lockqueue; /**<The value is that is stored, while the Control is locked
public:
Control(char ndefaultval); /**\todo create proper initialization list*/
~Control() {}
/**Return the string, which represents the internal value
* @return a string representation of the current value*/
virtual std::string getString() const = 0;
/**Set the Control to the given value
* @param nval A number 0-127*/
virtual void setmVal(char nval) = 0;
/**Return the midi value (aka the char)
* @return the current value*/
virtual char getmVal() const = 0;
/** Will lock the Control until it is ulocked
*
* Locking a Control will Stop it from having
* its internal data altered*/
void lock();
/** Will unlock the Control
*
* This will also update the Control
* if something attempted to update it while it was locked*/
void ulock();
private:
char defaultval; /**<Default value of the Control*/
char lockqueue; /**<The value is that is stored, while the Control is locked
* and something attempts to update it*/
bool locked;//upgrade this to a integer lock level if problems occur
bool locked; //upgrade this to a integer lock level if problems occur
};
#endif

View File

@@ -23,28 +23,29 @@
#include <sstream>
DelayCtl::DelayCtl()
:Control(64),value(64/127.0*1.5) {} /**\todo finishme*/
:Control(64), value(64 / 127.0 * 1.5) {} /**\todo finishme*/
std::string DelayCtl::getString() const
{
std::ostringstream buf;
buf<<value;
return (buf.str() + " Seconds");
buf << value;
return buf.str() + " Seconds";
}
void DelayCtl::setmVal(char nval)
{
/**\todo add locking code*/
//value=1+(int)(nval/127.0*SAMPLE_RATE*1.5);//0 .. 1.5 sec
value=(nval/127.0*1.5);//0 .. 1.5 sec
value = (nval / 127.0 * 1.5); //0 .. 1.5 sec
}
char DelayCtl::getmVal() const
{
return((char)(value/1.5*127.0));
return (char)(value / 1.5 * 127.0);
}
float DelayCtl::getiVal() const
{
return(value);
return value;
}

View File

@@ -28,15 +28,15 @@
* Will vary from 0 seconds to 1.5 seconds*/
class DelayCtl:public Control
{
public:
DelayCtl();
~DelayCtl() {};
std::string getString() const;
void setmVal(char nval);
char getmVal() const;
float getiVal() const;
private:
float value;
public:
DelayCtl();
~DelayCtl() {}
std::string getString() const;
void setmVal(char nval);
char getmVal() const;
float getiVal() const;
private:
float value;
};
#endif

View File

@@ -24,384 +24,427 @@
#include <stdio.h>
#include "AnalogFilter.h"
AnalogFilter::AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages)
AnalogFilter::AnalogFilter(unsigned char Ftype,
REALTYPE Ffreq,
REALTYPE Fq,
unsigned char Fstages)
{
stages=Fstages;
for (int i=0;i<3;i++) {
oldc[i]=0.0;
oldd[i]=0.0;
c[i]=0.0;
d[i]=0.0;
};
type=Ftype;
freq=Ffreq;
q=Fq;
gain=1.0;
if (stages>=MAX_FILTER_STAGES) stages=MAX_FILTER_STAGES;
stages = Fstages;
for(int i = 0; i < 3; i++) {
oldc[i] = 0.0;
oldd[i] = 0.0;
c[i] = 0.0;
d[i] = 0.0;
}
type = Ftype;
freq = Ffreq;
q = Fq;
gain = 1.0;
if(stages >= MAX_FILTER_STAGES)
stages = MAX_FILTER_STAGES;
cleanup();
firsttime=0;
abovenq=0;
oldabovenq=0;
setfreq_and_q(Ffreq,Fq);
firsttime=1;
d[0]=0;//this is not used
outgain=1.0;
};
firsttime = 0;
abovenq = 0;
oldabovenq = 0;
setfreq_and_q(Ffreq, Fq);
firsttime = 1;
d[0] = 0; //this is not used
outgain = 1.0;
}
AnalogFilter::~AnalogFilter()
{
};
{}
void AnalogFilter::cleanup()
{
for (int i=0;i<MAX_FILTER_STAGES+1;i++) {
x[i].c1=0.0;
x[i].c2=0.0;
y[i].c1=0.0;
y[i].c2=0.0;
oldx[i]=x[i];
oldy[i]=y[i];
};
needsinterpolation=0;
};
for(int i = 0; i < MAX_FILTER_STAGES + 1; i++) {
x[i].c1 = 0.0;
x[i].c2 = 0.0;
y[i].c1 = 0.0;
y[i].c2 = 0.0;
oldx[i] = x[i];
oldy[i] = y[i];
}
needsinterpolation = 0;
}
void AnalogFilter::computefiltercoefs()
{
REALTYPE tmp;
REALTYPE omega,sn,cs,alpha,beta;
int zerocoefs=0;//this is used if the freq is too high
REALTYPE omega, sn, cs, alpha, beta;
int zerocoefs = 0; //this is used if the freq is too high
//do not allow frequencies bigger than samplerate/2
REALTYPE freq=this->freq;
if (freq>(SAMPLE_RATE/2-500.0)) {
freq=SAMPLE_RATE/2-500.0;
zerocoefs=1;
};
if (freq<0.1) freq=0.1;
REALTYPE freq = this->freq;
if(freq > (SAMPLE_RATE / 2 - 500.0)) {
freq = SAMPLE_RATE / 2 - 500.0;
zerocoefs = 1;
}
if(freq < 0.1)
freq = 0.1;
//do not allow bogus Q
if (q<0.0) q=0.0;
REALTYPE tmpq,tmpgain;
if (stages==0) {
tmpq=q;
tmpgain=gain;
} else {
tmpq=(q>1.0 ? pow(q,1.0/(stages+1)) : q);
tmpgain=pow(gain,1.0/(stages+1));
};
if(q < 0.0)
q = 0.0;
REALTYPE tmpq, tmpgain;
if(stages == 0) {
tmpq = q;
tmpgain = gain;
}
else {
tmpq = (q > 1.0 ? pow(q, 1.0 / (stages + 1)) : q);
tmpgain = pow(gain, 1.0 / (stages + 1));
}
//most of theese are implementations of
//the "Cookbook formulae for audio EQ" by Robert Bristow-Johnson
//The original location of the Cookbook is:
//http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
switch (type) {
case 0://LPF 1 pole
if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE);
else tmp=0.0;
c[0]=1.0-tmp;
c[1]=0.0;
c[2]=0.0;
d[1]=tmp;
d[2]=0.0;
order=1;
switch(type) {
case 0: //LPF 1 pole
if(zerocoefs == 0)
tmp = exp(-2.0 * PI * freq / SAMPLE_RATE);
else
tmp = 0.0;
c[0] = 1.0 - tmp;
c[1] = 0.0;
c[2] = 0.0;
d[1] = tmp;
d[2] = 0.0;
order = 1;
break;
case 1://HPF 1 pole
if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE);
else tmp=0.0;
c[0]=(1.0+tmp)/2.0;
c[1]=-(1.0+tmp)/2.0;
c[2]=0.0;
d[1]=tmp;
d[2]=0.0;
order=1;
case 1: //HPF 1 pole
if(zerocoefs == 0)
tmp = exp(-2.0 * PI * freq / SAMPLE_RATE);
else
tmp = 0.0;
c[0] = (1.0 + tmp) / 2.0;
c[1] = -(1.0 + tmp) / 2.0;
c[2] = 0.0;
d[1] = tmp;
d[2] = 0.0;
order = 1;
break;
case 2://LPF 2 poles
if (zerocoefs==0) {
omega=2*PI*freq/SAMPLE_RATE;
sn=sin(omega);
cs=cos(omega);
alpha=sn/(2*tmpq);
tmp=1+alpha;
c[0]=(1.0-cs)/2.0/tmp;
c[1]=(1.0-cs)/tmp;
c[2]=(1.0-cs)/2.0/tmp;
d[1]=-2*cs/tmp*(-1);
d[2]=(1-alpha)/tmp*(-1);
} else {
c[0]=1.0;
c[1]=0.0;
c[2]=0.0;
d[1]=0.0;
d[2]=0.0;
};
order=2;
case 2: //LPF 2 poles
if(zerocoefs == 0) {
omega = 2 * PI * freq / SAMPLE_RATE;
sn = sin(omega);
cs = cos(omega);
alpha = sn / (2 * tmpq);
tmp = 1 + alpha;
c[0] = (1.0 - cs) / 2.0 / tmp;
c[1] = (1.0 - cs) / tmp;
c[2] = (1.0 - cs) / 2.0 / tmp;
d[1] = -2 * cs / tmp * (-1);
d[2] = (1 - alpha) / tmp * (-1);
}
else {
c[0] = 1.0;
c[1] = 0.0;
c[2] = 0.0;
d[1] = 0.0;
d[2] = 0.0;
}
order = 2;
break;
case 3://HPF 2 poles
if (zerocoefs==0) {
omega=2*PI*freq/SAMPLE_RATE;
sn=sin(omega);
cs=cos(omega);
alpha=sn/(2*tmpq);
tmp=1+alpha;
c[0]=(1.0+cs)/2.0/tmp;
c[1]=-(1.0+cs)/tmp;
c[2]=(1.0+cs)/2.0/tmp;
d[1]=-2*cs/tmp*(-1);
d[2]=(1-alpha)/tmp*(-1);
} else {
c[0]=0.0;
c[1]=0.0;
c[2]=0.0;
d[1]=0.0;
d[2]=0.0;
};
order=2;
case 3: //HPF 2 poles
if(zerocoefs == 0) {
omega = 2 * PI * freq / SAMPLE_RATE;
sn = sin(omega);
cs = cos(omega);
alpha = sn / (2 * tmpq);
tmp = 1 + alpha;
c[0] = (1.0 + cs) / 2.0 / tmp;
c[1] = -(1.0 + cs) / tmp;
c[2] = (1.0 + cs) / 2.0 / tmp;
d[1] = -2 * cs / tmp * (-1);
d[2] = (1 - alpha) / tmp * (-1);
}
else {
c[0] = 0.0;
c[1] = 0.0;
c[2] = 0.0;
d[1] = 0.0;
d[2] = 0.0;
}
order = 2;
break;
case 4://BPF 2 poles
if (zerocoefs==0) {
omega=2*PI*freq/SAMPLE_RATE;
sn=sin(omega);
cs=cos(omega);
alpha=sn/(2*tmpq);
tmp=1+alpha;
c[0]=alpha/tmp*sqrt(tmpq+1);
c[1]=0;
c[2]=-alpha/tmp*sqrt(tmpq+1);
d[1]=-2*cs/tmp*(-1);
d[2]=(1-alpha)/tmp*(-1);
} else {
c[0]=0.0;
c[1]=0.0;
c[2]=0.0;
d[1]=0.0;
d[2]=0.0;
};
order=2;
case 4: //BPF 2 poles
if(zerocoefs == 0) {
omega = 2 * PI * freq / SAMPLE_RATE;
sn = sin(omega);
cs = cos(omega);
alpha = sn / (2 * tmpq);
tmp = 1 + alpha;
c[0] = alpha / tmp *sqrt(tmpq + 1);
c[1] = 0;
c[2] = -alpha / tmp *sqrt(tmpq + 1);
d[1] = -2 * cs / tmp * (-1);
d[2] = (1 - alpha) / tmp * (-1);
}
else {
c[0] = 0.0;
c[1] = 0.0;
c[2] = 0.0;
d[1] = 0.0;
d[2] = 0.0;
}
order = 2;
break;
case 5://NOTCH 2 poles
if (zerocoefs==0) {
omega=2*PI*freq/SAMPLE_RATE;
sn=sin(omega);
cs=cos(omega);
alpha=sn/(2*sqrt(tmpq));
tmp=1+alpha;
c[0]=1/tmp;
c[1]=-2*cs/tmp;
c[2]=1/tmp;
d[1]=-2*cs/tmp*(-1);
d[2]=(1-alpha)/tmp*(-1);
} else {
c[0]=1.0;
c[1]=0.0;
c[2]=0.0;
d[1]=0.0;
d[2]=0.0;
};
order=2;
case 5: //NOTCH 2 poles
if(zerocoefs == 0) {
omega = 2 * PI * freq / SAMPLE_RATE;
sn = sin(omega);
cs = cos(omega);
alpha = sn / (2 * sqrt(tmpq));
tmp = 1 + alpha;
c[0] = 1 / tmp;
c[1] = -2 * cs / tmp;
c[2] = 1 / tmp;
d[1] = -2 * cs / tmp * (-1);
d[2] = (1 - alpha) / tmp * (-1);
}
else {
c[0] = 1.0;
c[1] = 0.0;
c[2] = 0.0;
d[1] = 0.0;
d[2] = 0.0;
}
order = 2;
break;
case 6://PEAK (2 poles)
if (zerocoefs==0) {
omega=2*PI*freq/SAMPLE_RATE;
sn=sin(omega);
cs=cos(omega);
tmpq*=3.0;
alpha=sn/(2*tmpq);
tmp=1+alpha/tmpgain;
c[0]=(1.0+alpha*tmpgain)/tmp;
c[1]=(-2.0*cs)/tmp;
c[2]=(1.0-alpha*tmpgain)/tmp;
d[1]=-2*cs/tmp*(-1);
d[2]=(1-alpha/tmpgain)/tmp*(-1);
} else {
c[0]=1.0;
c[1]=0.0;
c[2]=0.0;
d[1]=0.0;
d[2]=0.0;
};
order=2;
case 6: //PEAK (2 poles)
if(zerocoefs == 0) {
omega = 2 * PI * freq / SAMPLE_RATE;
sn = sin(omega);
cs = cos(omega);
tmpq *= 3.0;
alpha = sn / (2 * tmpq);
tmp = 1 + alpha / tmpgain;
c[0] = (1.0 + alpha * tmpgain) / tmp;
c[1] = (-2.0 * cs) / tmp;
c[2] = (1.0 - alpha * tmpgain) / tmp;
d[1] = -2 * cs / tmp * (-1);
d[2] = (1 - alpha / tmpgain) / tmp * (-1);
}
else {
c[0] = 1.0;
c[1] = 0.0;
c[2] = 0.0;
d[1] = 0.0;
d[2] = 0.0;
}
order = 2;
break;
case 7://Low Shelf - 2 poles
if (zerocoefs==0) {
omega=2*PI*freq/SAMPLE_RATE;
sn=sin(omega);
cs=cos(omega);
tmpq=sqrt(tmpq);
alpha=sn/(2*tmpq);
beta=sqrt(tmpgain)/tmpq;
tmp=(tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn;
case 7: //Low Shelf - 2 poles
if(zerocoefs == 0) {
omega = 2 * PI * freq / SAMPLE_RATE;
sn = sin(omega);
cs = cos(omega);
tmpq = sqrt(tmpq);
alpha = sn / (2 * tmpq);
beta = sqrt(tmpgain) / tmpq;
tmp = (tmpgain + 1.0) + (tmpgain - 1.0) * cs + beta * sn;
c[0]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn)/tmp;
c[1]=2.0*tmpgain*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp;
c[2]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp;
d[1]=-2.0*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp*(-1);
d[2]=((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp*(-1);
} else {
c[0]=tmpgain;
c[1]=0.0;
c[2]=0.0;
d[1]=0.0;
d[2]=0.0;
};
order=2;
c[0] = tmpgain
* ((tmpgain
+ 1.0) - (tmpgain - 1.0) * cs + beta * sn) / tmp;
c[1] = 2.0 * tmpgain
* ((tmpgain - 1.0) - (tmpgain + 1.0) * cs) / tmp;
c[2] = tmpgain
* ((tmpgain
+ 1.0) - (tmpgain - 1.0) * cs - beta * sn) / tmp;
d[1] = -2.0 * ((tmpgain - 1.0) + (tmpgain + 1.0) * cs) / tmp * (-1);
d[2] =
((tmpgain
+ 1.0) + (tmpgain - 1.0) * cs - beta * sn) / tmp * (-1);
}
else {
c[0] = tmpgain;
c[1] = 0.0;
c[2] = 0.0;
d[1] = 0.0;
d[2] = 0.0;
}
order = 2;
break;
case 8://High Shelf - 2 poles
if (zerocoefs==0) {
omega=2*PI*freq/SAMPLE_RATE;
sn=sin(omega);
cs=cos(omega);
tmpq=sqrt(tmpq);
alpha=sn/(2*tmpq);
beta=sqrt(tmpgain)/tmpq;
tmp=(tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn;
case 8: //High Shelf - 2 poles
if(zerocoefs == 0) {
omega = 2 * PI * freq / SAMPLE_RATE;
sn = sin(omega);
cs = cos(omega);
tmpq = sqrt(tmpq);
alpha = sn / (2 * tmpq);
beta = sqrt(tmpgain) / tmpq;
tmp = (tmpgain + 1.0) - (tmpgain - 1.0) * cs + beta * sn;
c[0]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn)/tmp;
c[1]=-2.0*tmpgain*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp;
c[2]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp;
d[1]=2.0*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp*(-1);
d[2]=((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp*(-1);
} else {
c[0]=1.0;
c[1]=0.0;
c[2]=0.0;
d[1]=0.0;
d[2]=0.0;
};
order=2;
c[0] = tmpgain
* ((tmpgain
+ 1.0) + (tmpgain - 1.0) * cs + beta * sn) / tmp;
c[1] = -2.0 * tmpgain
* ((tmpgain - 1.0) + (tmpgain + 1.0) * cs) / tmp;
c[2] = tmpgain
* ((tmpgain
+ 1.0) + (tmpgain - 1.0) * cs - beta * sn) / tmp;
d[1] = 2.0 * ((tmpgain - 1.0) - (tmpgain + 1.0) * cs) / tmp * (-1);
d[2] =
((tmpgain
+ 1.0) - (tmpgain - 1.0) * cs - beta * sn) / tmp * (-1);
}
else {
c[0] = 1.0;
c[1] = 0.0;
c[2] = 0.0;
d[1] = 0.0;
d[2] = 0.0;
}
order = 2;
break;
default://wrong type
type=0;
default: //wrong type
type = 0;
computefiltercoefs();
break;
};
};
}
}
void AnalogFilter::setfreq(REALTYPE frequency)
{
if (frequency<0.1) frequency=0.1;
REALTYPE rap=freq/frequency;
if (rap<1.0) rap=1.0/rap;
if(frequency < 0.1)
frequency = 0.1;
REALTYPE rap = freq / frequency;
if(rap < 1.0)
rap = 1.0 / rap;
oldabovenq=abovenq;
abovenq=frequency>(SAMPLE_RATE/2-500.0);
oldabovenq = abovenq;
abovenq = frequency > (SAMPLE_RATE / 2 - 500.0);
int nyquistthresh=(abovenq^oldabovenq);
int nyquistthresh = (abovenq ^ oldabovenq);
if ((rap>3.0)||(nyquistthresh!=0)) {//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup)
for (int i=0;i<3;i++) {
oldc[i]=c[i];
oldd[i]=d[i];
};
for (int i=0;i<MAX_FILTER_STAGES+1;i++) {
oldx[i]=x[i];
oldy[i]=y[i];
};
if (firsttime==0) needsinterpolation=1;
};
freq=frequency;
if((rap > 3.0) || (nyquistthresh != 0)) { //if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup)
for(int i = 0; i < 3; i++) {
oldc[i] = c[i];
oldd[i] = d[i];
}
for(int i = 0; i < MAX_FILTER_STAGES + 1; i++) {
oldx[i] = x[i];
oldy[i] = y[i];
}
if(firsttime == 0)
needsinterpolation = 1;
}
freq = frequency;
computefiltercoefs();
firsttime=0;
firsttime = 0;
}
};
void AnalogFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_)
void AnalogFilter::setfreq_and_q(REALTYPE frequency, REALTYPE q_)
{
q=q_;
q = q_;
setfreq(frequency);
};
}
void AnalogFilter::setq(REALTYPE q_)
{
q=q_;
q = q_;
computefiltercoefs();
};
}
void AnalogFilter::settype(int type_)
{
type=type_;
type = type_;
computefiltercoefs();
};
}
void AnalogFilter::setgain(REALTYPE dBgain)
{
gain=dB2rap(dBgain);
gain = dB2rap(dBgain);
computefiltercoefs();
};
}
void AnalogFilter::setstages(int stages_)
{
if (stages_>=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1;
stages=stages_;
if(stages_ >= MAX_FILTER_STAGES)
stages_ = MAX_FILTER_STAGES - 1;
stages = stages_;
cleanup();
computefiltercoefs();
};
}
void AnalogFilter::singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d)
void AnalogFilter::singlefilterout(REALTYPE *smp,
fstage &x,
fstage &y,
REALTYPE *c,
REALTYPE *d)
{
int i;
int i;
REALTYPE y0;
if (order==1) {//First order filter
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
y0=smp[i]*c[0]+x.c1*c[1]+y.c1*d[1];
y.c1=y0;
x.c1=smp[i];
if(order == 1) { //First order filter
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
y0 = smp[i] * c[0] + x.c1 * c[1] + y.c1 * d[1];
y.c1 = y0;
x.c1 = smp[i];
//output
smp[i]=y0;
};
};
if (order==2) {//Second order filter
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
y0=smp[i]*c[0]+x.c1*c[1]+x.c2*c[2]+y.c1*d[1]+y.c2*d[2];
y.c2=y.c1;
y.c1=y0;
x.c2=x.c1;
x.c1=smp[i];
smp[i] = y0;
}
}
if(order == 2) { //Second order filter
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
y0 = smp[i] * c[0] + x.c1 * c[1] + x.c2 * c[2] + y.c1 * d[1]
+ y.c2 * d[2];
y.c2 = y.c1;
y.c1 = y0;
x.c2 = x.c1;
x.c1 = smp[i];
//output
smp[i]=y0;
};
};
};
smp[i] = y0;
}
}
}
void AnalogFilter::filterout(REALTYPE *smp)
{
REALTYPE *ismp=NULL;//used if it needs interpolation
REALTYPE *ismp = NULL; //used if it needs interpolation
int i;
if (needsinterpolation!=0) {
ismp=new REALTYPE[SOUND_BUFFER_SIZE];
for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i];
for (i=0;i<stages+1;i++) singlefilterout(ismp,oldx[i],oldy[i],oldc,oldd);
};
if(needsinterpolation != 0) {
ismp = new REALTYPE[SOUND_BUFFER_SIZE];
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
ismp[i] = smp[i];
for(i = 0; i < stages + 1; i++)
singlefilterout(ismp, oldx[i], oldy[i], oldc, oldd);
}
for (i=0;i<stages+1;i++) singlefilterout(smp,x[i],y[i],c,d);
for(i = 0; i < stages + 1; i++)
singlefilterout(smp, x[i], y[i], c, d);
if (needsinterpolation!=0) {
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE;
smp[i]=ismp[i]*(1.0-x)+smp[i]*x;
};
if(needsinterpolation != 0) {
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
REALTYPE x = i / (REALTYPE) SOUND_BUFFER_SIZE;
smp[i] = ismp[i] * (1.0 - x) + smp[i] * x;
}
delete [] ismp;
needsinterpolation=0;
};
needsinterpolation = 0;
}
for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]*=outgain;
};
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
smp[i] *= outgain;
}
REALTYPE AnalogFilter::H(REALTYPE freq)
{
REALTYPE fr=freq/SAMPLE_RATE*PI*2.0;
REALTYPE x=c[0],y=0.0;
for (int n=1;n<3;n++) {
x+=cos(n*fr)*c[n];
y-=sin(n*fr)*c[n];
};
REALTYPE h=x*x+y*y;
x=1.0;
y=0.0;
for (int n=1;n<3;n++) {
x-=cos(n*fr)*d[n];
y+=sin(n*fr)*d[n];
};
h=h/(x*x+y*y);
return(pow(h,(stages+1.0)/2.0));
};
REALTYPE fr = freq / SAMPLE_RATE * PI * 2.0;
REALTYPE x = c[0], y = 0.0;
for(int n = 1; n < 3; n++) {
x += cos(n * fr) * c[n];
y -= sin(n * fr) * c[n];
}
REALTYPE h = x * x + y * y;
x = 1.0;
y = 0.0;
for(int n = 1; n < 3; n++) {
x -= cos(n * fr) * d[n];
y += sin(n * fr) * d[n];
}
h = h / (x * x + y * y);
return pow(h, (stages + 1.0) / 2.0);
}

View File

@@ -29,45 +29,52 @@
/**Implementation of Several analog filters (lowpass, highpass...)*/
class AnalogFilter:public Filter_
{
public:
AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages);
~AnalogFilter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency,REALTYPE q_);
void setq(REALTYPE q_);
public:
AnalogFilter(unsigned char Ftype,
REALTYPE Ffreq,
REALTYPE Fq,
unsigned char Fstages);
~AnalogFilter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency, REALTYPE q_);
void setq(REALTYPE q_);
void settype(int type_);
void setgain(REALTYPE dBgain);
void setstages(int stages_);
void cleanup();
void settype(int type_);
void setgain(REALTYPE dBgain);
void setstages(int stages_);
void cleanup();
REALTYPE H(REALTYPE freq);//Obtains the response for a given frequency
REALTYPE H(REALTYPE freq); //Obtains the response for a given frequency
private:
struct fstage {
REALTYPE c1,c2;
} x[MAX_FILTER_STAGES+1],y[MAX_FILTER_STAGES+1],
oldx[MAX_FILTER_STAGES+1],oldy[MAX_FILTER_STAGES+1];
private:
struct fstage {
REALTYPE c1, c2;
} x[MAX_FILTER_STAGES + 1], y[MAX_FILTER_STAGES + 1],
oldx[MAX_FILTER_STAGES + 1], oldy[MAX_FILTER_STAGES + 1];
void singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d);
void computefiltercoefs();
int type;//The type of the filter (LPF1,HPF1,LPF2,HPF2...)
int stages;//how many times the filter is applied (0->1,1->2,etc.)
REALTYPE freq;//Frequency given in Hz
REALTYPE q; //Q factor (resonance or Q factor)
REALTYPE gain;//the gain of the filter (if are shelf/peak) filters
void singlefilterout(REALTYPE *smp,
fstage &x,
fstage &y,
REALTYPE *c,
REALTYPE *d);
void computefiltercoefs();
int type; //The type of the filter (LPF1,HPF1,LPF2,HPF2...)
int stages; //how many times the filter is applied (0->1,1->2,etc.)
REALTYPE freq; //Frequency given in Hz
REALTYPE q; //Q factor (resonance or Q factor)
REALTYPE gain; //the gain of the filter (if are shelf/peak) filters
int order;//the order of the filter (number of poles)
int order; //the order of the filter (number of poles)
REALTYPE c[3],d[3];//coefficients
REALTYPE c[3], d[3]; //coefficients
REALTYPE oldc[3],oldd[3];//old coefficients(used only if some filter paremeters changes very fast, and it needs interpolation)
REALTYPE oldc[3], oldd[3]; //old coefficients(used only if some filter paremeters changes very fast, and it needs interpolation)
REALTYPE xd[3],yd[3];//used if the filter is applied more times
int needsinterpolation,firsttime;/**\todo see if bool works for these*/
int abovenq;//this is 1 if the frequency is above the nyquist
int oldabovenq;//if the last time was above nyquist (used to see if it needs interpolation)
REALTYPE xd[3], yd[3]; //used if the filter is applied more times
int needsinterpolation, firsttime; /**\todo see if bool works for these*/
int abovenq; //this is 1 if the frequency is above the nyquist
int oldabovenq; //if the last time was above nyquist (used to see if it needs interpolation)
};

View File

@@ -4,6 +4,7 @@ set(zynaddsubfx_dsp_SRCS
Filter.cpp
FormantFilter.cpp
SVFilter.cpp
Unison.cpp
)
add_library(zynaddsubfx_dsp STATIC

View File

@@ -25,17 +25,29 @@
FFTwrapper::FFTwrapper(int fftsize_)
{
fftsize=fftsize_;
tmpfftdata1=new fftw_real[fftsize];
tmpfftdata2=new fftw_real[fftsize];
fftsize = fftsize_;
tmpfftdata1 = new fftw_real[fftsize];
tmpfftdata2 = new fftw_real[fftsize];
#ifdef FFTW_VERSION_2
planfftw=rfftw_create_plan(fftsize,FFTW_REAL_TO_COMPLEX,FFTW_ESTIMATE|FFTW_IN_PLACE);
planfftw_inv=rfftw_create_plan(fftsize,FFTW_COMPLEX_TO_REAL,FFTW_ESTIMATE|FFTW_IN_PLACE);
planfftw = rfftw_create_plan(fftsize,
FFTW_REAL_TO_COMPLEX,
FFTW_ESTIMATE | FFTW_IN_PLACE);
planfftw_inv = rfftw_create_plan(fftsize,
FFTW_COMPLEX_TO_REAL,
FFTW_ESTIMATE | FFTW_IN_PLACE);
#else
planfftw=fftwf_plan_r2r_1d(fftsize,tmpfftdata1,tmpfftdata1,FFTW_R2HC,FFTW_ESTIMATE);
planfftw_inv=fftwf_plan_r2r_1d(fftsize,tmpfftdata2,tmpfftdata2,FFTW_HC2R,FFTW_ESTIMATE);
planfftw = fftwf_plan_r2r_1d(fftsize,
tmpfftdata1,
tmpfftdata1,
FFTW_R2HC,
FFTW_ESTIMATE);
planfftw_inv = fftwf_plan_r2r_1d(fftsize,
tmpfftdata2,
tmpfftdata2,
FFTW_HC2R,
FFTW_ESTIMATE);
#endif
};
}
FFTwrapper::~FFTwrapper()
{
@@ -49,52 +61,76 @@ FFTwrapper::~FFTwrapper()
delete [] tmpfftdata1;
delete [] tmpfftdata2;
};
}
/*
* do the Fast Fourier Transform
*/
void FFTwrapper::smps2freqs(REALTYPE *smps,FFTFREQS freqs)
void FFTwrapper::smps2freqs(REALTYPE *smps, FFTFREQS freqs)
{
#ifdef FFTW_VERSION_2
for (int i=0;i<fftsize;i++) tmpfftdata1[i]=smps[i];
rfftw_one(planfftw,tmpfftdata1,tmpfftdata2);
for (int i=0;i<fftsize/2;i++) {
freqs.c[i]=tmpfftdata2[i];
if (i!=0) freqs.s[i]=tmpfftdata2[fftsize-i];
};
for(int i = 0; i < fftsize; i++)
tmpfftdata1[i] = smps[i];
rfftw_one(planfftw, tmpfftdata1, tmpfftdata2);
for(int i = 0; i < fftsize / 2; i++) {
freqs.c[i] = tmpfftdata2[i];
if(i != 0)
freqs.s[i] = tmpfftdata2[fftsize - i];
}
#else
for (int i=0;i<fftsize;i++) tmpfftdata1[i]=smps[i];
for(int i = 0; i < fftsize; i++)
tmpfftdata1[i] = smps[i];
fftwf_execute(planfftw);
for (int i=0;i<fftsize/2;i++) {
freqs.c[i]=tmpfftdata1[i];
if (i!=0) freqs.s[i]=tmpfftdata1[fftsize-i];
};
for(int i = 0; i < fftsize / 2; i++) {
freqs.c[i] = tmpfftdata1[i];
if(i != 0)
freqs.s[i] = tmpfftdata1[fftsize - i];
}
#endif
tmpfftdata2[fftsize/2]=0.0;
};
tmpfftdata2[fftsize / 2] = 0.0;
}
/*
* do the Inverse Fast Fourier Transform
*/
void FFTwrapper::freqs2smps(FFTFREQS freqs,REALTYPE *smps)
void FFTwrapper::freqs2smps(FFTFREQS freqs, REALTYPE *smps)
{
tmpfftdata2[fftsize/2]=0.0;
tmpfftdata2[fftsize / 2] = 0.0;
#ifdef FFTW_VERSION_2
for (int i=0;i<fftsize/2;i++) {
tmpfftdata1[i]=freqs.c[i];
if (i!=0) tmpfftdata1[fftsize-i]=freqs.s[i];
};
rfftw_one(planfftw_inv,tmpfftdata1,tmpfftdata2);
for (int i=0;i<fftsize;i++) smps[i]=tmpfftdata2[i];
for(int i = 0; i < fftsize / 2; i++) {
tmpfftdata1[i] = freqs.c[i];
if(i != 0)
tmpfftdata1[fftsize - i] = freqs.s[i];
}
rfftw_one(planfftw_inv, tmpfftdata1, tmpfftdata2);
for(int i = 0; i < fftsize; i++)
smps[i] = tmpfftdata2[i];
#else
for (int i=0;i<fftsize/2;i++) {
tmpfftdata2[i]=freqs.c[i];
if (i!=0) tmpfftdata2[fftsize-i]=freqs.s[i];
};
for(int i = 0; i < fftsize / 2; i++) {
tmpfftdata2[i] = freqs.c[i];
if(i != 0)
tmpfftdata2[fftsize - i] = freqs.s[i];
}
fftwf_execute(planfftw_inv);
for (int i=0;i<fftsize;i++) smps[i]=tmpfftdata2[i];
for(int i = 0; i < fftsize; i++)
smps[i] = tmpfftdata2[i];
#endif
}
};
void newFFTFREQS(FFTFREQS *f, int size)
{
f->c = new REALTYPE[size];
f->s = new REALTYPE[size];
for(int i = 0; i < size; i++) {
f->c[i] = 0.0;
f->s[i] = 0.0;
}
}
void deleteFFTFREQS(FFTFREQS *f)
{
delete[] f->c;
delete[] f->s;
f->c = f->s = NULL;
}

View File

@@ -47,21 +47,24 @@ Hope all goes right." */
/**A wrapper for the FFTW library (Fast Fourier Transforms)*/
class FFTwrapper
{
public:
/**Constructor
* @param fftsize The size of samples to be fed to fftw*/
FFTwrapper(int fftsize_);
/**Destructor*/
~FFTwrapper();
/**Convert Samples to Frequencies using Fourier Transform
* @param smps Pointer to Samples to be converted; has length fftsize_
* @param freqs Structure FFTFREQS which stores the frequencies*/
void smps2freqs(REALTYPE *smps,FFTFREQS freqs);
void freqs2smps(FFTFREQS freqs,REALTYPE *smps);
private:
int fftsize;
fftw_real *tmpfftdata1,*tmpfftdata2;
rfftw_plan planfftw,planfftw_inv;
public:
/**Constructor
* @param fftsize The size of samples to be fed to fftw*/
FFTwrapper(int fftsize_);
/**Destructor*/
~FFTwrapper();
/**Convert Samples to Frequencies using Fourier Transform
* @param smps Pointer to Samples to be converted; has length fftsize_
* @param freqs Structure FFTFREQS which stores the frequencies*/
void smps2freqs(REALTYPE *smps, FFTFREQS freqs);
void freqs2smps(FFTFREQS freqs, REALTYPE *smps);
private:
int fftsize;
fftw_real *tmpfftdata1, *tmpfftdata2;
rfftw_plan planfftw, planfftw_inv;
};
void newFFTFREQS(FFTFREQS *f, int size);
void deleteFFTFREQS(FFTFREQS *f);
#endif

View File

@@ -27,56 +27,61 @@
Filter::Filter(FilterParams *pars)
{
unsigned char Ftype=pars->Ptype;
unsigned char Fstages=pars->Pstages;
unsigned char Ftype = pars->Ptype;
unsigned char Fstages = pars->Pstages;
category=pars->Pcategory;
category = pars->Pcategory;
switch (category) {
switch(category) {
case 1:
filter=new FormantFilter(pars);
filter = new FormantFilter(pars);
break;
case 2:
filter=new SVFilter(Ftype,1000.0,pars->getq(),Fstages);
filter->outgain=dB2rap(pars->getgain());
if (filter->outgain>1.0) filter->outgain=sqrt(filter->outgain);
filter = new SVFilter(Ftype, 1000.0, pars->getq(), Fstages);
filter->outgain = dB2rap(pars->getgain());
if(filter->outgain > 1.0)
filter->outgain = sqrt(filter->outgain);
break;
default:
filter=new AnalogFilter(Ftype,1000.0,pars->getq(),Fstages);
if ((Ftype>=6)&&(Ftype<=8)) filter->setgain(pars->getgain());
else filter->outgain=dB2rap(pars->getgain());
filter = new AnalogFilter(Ftype, 1000.0, pars->getq(), Fstages);
if((Ftype >= 6) && (Ftype <= 8))
filter->setgain(pars->getgain());
else
filter->outgain = dB2rap(pars->getgain());
break;
};
};
}
}
Filter::~Filter()
{
delete (filter);
};
}
void Filter::filterout(REALTYPE *smp)
{
filter->filterout(smp);
};
}
void Filter::setfreq(REALTYPE frequency)
{
filter->setfreq(frequency);
};
}
void Filter::setfreq_and_q(REALTYPE frequency,REALTYPE q_)
void Filter::setfreq_and_q(REALTYPE frequency, REALTYPE q_)
{
filter->setfreq_and_q(frequency,q_);
};
filter->setfreq_and_q(frequency, q_);
}
void Filter::setq(REALTYPE q_)
{
filter->setq(q_);
};
}
REALTYPE Filter::getrealfreq(REALTYPE freqpitch)
{
if ((category==0)||(category==2)) return(pow(2.0,freqpitch+9.96578428));//log2(1000)=9.95748
else return(freqpitch);
};
if((category == 0) || (category == 2))
return pow(2.0, freqpitch + 9.96578428); //log2(1000)=9.95748
else
return freqpitch;
}

View File

@@ -33,18 +33,18 @@
class Filter
{
public:
Filter(FilterParams *pars);
~Filter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency,REALTYPE q_);
void setq(REALTYPE q_);
public:
Filter(FilterParams *pars);
~Filter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency, REALTYPE q_);
void setq(REALTYPE q_);
REALTYPE getrealfreq(REALTYPE freqpitch);
private:
Filter_ *filter;
unsigned char category;
REALTYPE getrealfreq(REALTYPE freqpitch);
private:
Filter_ *filter;
unsigned char category;
};

View File

@@ -27,15 +27,15 @@
class Filter_
{
public:
virtual ~Filter_() {};
virtual void filterout(REALTYPE *smp)=0;
virtual void setfreq(REALTYPE frequency)=0;
virtual void setfreq_and_q(REALTYPE frequency,REALTYPE q_)=0;
virtual void setq(REALTYPE q_)=0;
virtual void setgain(REALTYPE dBgain) {};
REALTYPE outgain;
private:
public:
virtual ~Filter_() {}
virtual void filterout(REALTYPE *smp) = 0;
virtual void setfreq(REALTYPE frequency) = 0;
virtual void setfreq_and_q(REALTYPE frequency, REALTYPE q_) = 0;
virtual void setq(REALTYPE q_) = 0;
virtual void setgain(REALTYPE dBgain) {}
REALTYPE outgain;
private:
};

View File

@@ -26,151 +26,202 @@
FormantFilter::FormantFilter(FilterParams *pars)
{
numformants=pars->Pnumformants;
for (int i=0;i<numformants;i++) formant[i]=new AnalogFilter(4/*BPF*/,1000.0,10.0,pars->Pstages);
numformants = pars->Pnumformants;
for(int i = 0; i < numformants; i++)
formant[i] = new AnalogFilter(4 /*BPF*/, 1000.0, 10.0, pars->Pstages);
cleanup();
inbuffer=new REALTYPE [SOUND_BUFFER_SIZE];
tmpbuf=new REALTYPE [SOUND_BUFFER_SIZE];
inbuffer = new REALTYPE [SOUND_BUFFER_SIZE];
tmpbuf = new REALTYPE [SOUND_BUFFER_SIZE];
for (int j=0;j<FF_MAX_VOWELS;j++)
for (int i=0;i<numformants;i++) {
formantpar[j][i].freq=pars->getformantfreq(pars->Pvowels[j].formants[i].freq);
formantpar[j][i].amp=pars->getformantamp(pars->Pvowels[j].formants[i].amp);
formantpar[j][i].q=pars->getformantq(pars->Pvowels[j].formants[i].q);
};
for (int i=0;i<FF_MAX_FORMANTS;i++) oldformantamp[i]=1.0;
for (int i=0;i<numformants;i++) {
currentformants[i].freq=1000.0;
currentformants[i].amp=1.0;
currentformants[i].q=2.0;
};
for(int j = 0; j < FF_MAX_VOWELS; j++)
for(int i = 0; i < numformants; i++) {
formantpar[j][i].freq = pars->getformantfreq(
pars->Pvowels[j].formants[i].freq);
formantpar[j][i].amp = pars->getformantamp(
pars->Pvowels[j].formants[i].amp);
formantpar[j][i].q = pars->getformantq(
pars->Pvowels[j].formants[i].q);
}
;
for(int i = 0; i < FF_MAX_FORMANTS; i++)
oldformantamp[i] = 1.0;
for(int i = 0; i < numformants; i++) {
currentformants[i].freq = 1000.0;
currentformants[i].amp = 1.0;
currentformants[i].q = 2.0;
}
formantslowness=pow(1.0-(pars->Pformantslowness/128.0),3.0);
formantslowness = pow(1.0 - (pars->Pformantslowness / 128.0), 3.0);
sequencesize=pars->Psequencesize;
if (sequencesize==0) sequencesize=1;
for (int k=0;k<sequencesize;k++) sequence[k].nvowel=pars->Psequence[k].nvowel;
sequencesize = pars->Psequencesize;
if(sequencesize == 0)
sequencesize = 1;
for(int k = 0; k < sequencesize; k++)
sequence[k].nvowel = pars->Psequence[k].nvowel;
vowelclearness=pow(10.0,(pars->Pvowelclearness-32.0)/48.0);
vowelclearness = pow(10.0, (pars->Pvowelclearness - 32.0) / 48.0);
sequencestretch=pow(0.1,(pars->Psequencestretch-32.0)/48.0);
if (pars->Psequencereversed) sequencestretch*= -1.0;
sequencestretch = pow(0.1, (pars->Psequencestretch - 32.0) / 48.0);
if(pars->Psequencereversed)
sequencestretch *= -1.0;
outgain=dB2rap(pars->getgain());
outgain = dB2rap(pars->getgain());
oldinput=-1.0;
Qfactor=1.0;
oldQfactor=Qfactor;
firsttime=1;
};
oldinput = -1.0;
Qfactor = 1.0;
oldQfactor = Qfactor;
firsttime = 1;
}
FormantFilter::~FormantFilter()
{
for (int i=0;i<numformants;i++) delete(formant[i]);
for(int i = 0; i < numformants; i++)
delete (formant[i]);
delete[] inbuffer;
delete[] tmpbuf;
};
}
void FormantFilter::cleanup()
{
for (int i=0;i<numformants;i++) formant[i]->cleanup();
};
for(int i = 0; i < numformants; i++)
formant[i]->cleanup();
}
void FormantFilter::setpos(REALTYPE input)
{
int p1,p2;
int p1, p2;
if (firsttime!=0) slowinput=input;
else slowinput=slowinput*(1.0-formantslowness)+input*formantslowness;
if(firsttime != 0)
slowinput = input;
else
slowinput = slowinput
* (1.0 - formantslowness) + input * formantslowness;
if ((fabs(oldinput-input)<0.001)&&(fabs(slowinput-input)<0.001)&&
(fabs(Qfactor-oldQfactor)<0.001)) {
if((fabs(oldinput - input) < 0.001) && (fabs(slowinput - input) < 0.001)
&& (fabs(Qfactor - oldQfactor) < 0.001)) {
// oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente
firsttime=0;
firsttime = 0;
return;
} else oldinput=input;
}
else
oldinput = input;
REALTYPE pos=fmod(input*sequencestretch,1.0);
if (pos<0.0) pos+=1.0;
REALTYPE pos = fmod(input * sequencestretch, 1.0);
if(pos < 0.0)
pos += 1.0;
F2I(pos*sequencesize,p2);
p1=p2-1;
if (p1<0) p1+=sequencesize;
F2I(pos * sequencesize, p2);
p1 = p2 - 1;
if(p1 < 0)
p1 += sequencesize;
pos=fmod(pos*sequencesize,1.0);
if (pos<0.0) pos=0.0;
else if (pos>1.0) pos=1.0;
pos=(atan((pos*2.0-1.0)*vowelclearness)/atan(vowelclearness)+1.0)*0.5;
pos = fmod(pos * sequencesize, 1.0);
if(pos < 0.0)
pos = 0.0;
else
if(pos > 1.0)
pos = 1.0;
pos =
(atan((pos * 2.0
- 1.0) * vowelclearness) / atan(vowelclearness) + 1.0) * 0.5;
p1=sequence[p1].nvowel;
p2=sequence[p2].nvowel;
p1 = sequence[p1].nvowel;
p2 = sequence[p2].nvowel;
if (firsttime!=0) {
for (int i=0;i<numformants;i++) {
currentformants[i].freq=formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos;
currentformants[i].amp=formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos;
currentformants[i].q=formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos;
formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor);
oldformantamp[i]=currentformants[i].amp;
};
firsttime=0;
} else {
for (int i=0;i<numformants;i++) {
currentformants[i].freq=currentformants[i].freq*(1.0-formantslowness)
+(formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos)*formantslowness;
if(firsttime != 0) {
for(int i = 0; i < numformants; i++) {
currentformants[i].freq = formantpar[p1][i].freq
* (1.0
- pos) + formantpar[p2][i].freq * pos;
currentformants[i].amp = formantpar[p1][i].amp
* (1.0
- pos) + formantpar[p2][i].amp * pos;
currentformants[i].q = formantpar[p1][i].q
* (1.0 - pos) + formantpar[p2][i].q * pos;
formant[i]->setfreq_and_q(currentformants[i].freq,
currentformants[i].q * Qfactor);
oldformantamp[i] = currentformants[i].amp;
}
firsttime = 0;
}
else {
for(int i = 0; i < numformants; i++) {
currentformants[i].freq = currentformants[i].freq
* (1.0 - formantslowness)
+ (formantpar[p1][i].freq
* (1.0
- pos) + formantpar[p2][i].freq
* pos) * formantslowness;
currentformants[i].amp=currentformants[i].amp*(1.0-formantslowness)
+(formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos)*formantslowness;
currentformants[i].amp = currentformants[i].amp
* (1.0 - formantslowness)
+ (formantpar[p1][i].amp
* (1.0
- pos) + formantpar[p2][i].amp
* pos) * formantslowness;
currentformants[i].q=currentformants[i].q*(1.0-formantslowness)
+(formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos)*formantslowness;
currentformants[i].q = currentformants[i].q
* (1.0 - formantslowness)
+ (formantpar[p1][i].q
* (1.0
- pos) + formantpar[p2][i].q
* pos) * formantslowness;
formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor);
};
};
formant[i]->setfreq_and_q(currentformants[i].freq,
currentformants[i].q * Qfactor);
}
}
oldQfactor=Qfactor;
};
oldQfactor = Qfactor;
}
void FormantFilter::setfreq(REALTYPE frequency)
{
setpos(frequency);
};
}
void FormantFilter::setq(REALTYPE q_)
{
Qfactor=q_;
for (int i=0;i<numformants;i++) formant[i]->setq(Qfactor*currentformants[i].q);
};
Qfactor = q_;
for(int i = 0; i < numformants; i++)
formant[i]->setq(Qfactor * currentformants[i].q);
}
void FormantFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_)
void FormantFilter::setfreq_and_q(REALTYPE frequency, REALTYPE q_)
{
Qfactor=q_;
Qfactor = q_;
setpos(frequency);
};
}
void FormantFilter::filterout(REALTYPE *smp)
{
int i,j;
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
inbuffer[i]=smp[i];
smp[i]=0.0;
};
int i, j;
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
inbuffer[i] = smp[i];
smp[i] = 0.0;
}
for (j=0;j<numformants;j++) {
for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpbuf[i]=inbuffer[i]*outgain;
for(j = 0; j < numformants; j++) {
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
tmpbuf[i] = inbuffer[i] * outgain;
formant[j]->filterout(tmpbuf);
if (ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j],currentformants[j].amp))
for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]*
INTERPOLATE_AMPLITUDE(oldformantamp[j],currentformants[j].amp,i,SOUND_BUFFER_SIZE);
else for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]*currentformants[j].amp;
oldformantamp[j]=currentformants[j].amp;
};
};
if(ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j], currentformants[j].amp))
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
smp[i] += tmpbuf[i]
* INTERPOLATE_AMPLITUDE(oldformantamp[j],
currentformants[j].amp,
i,
SOUND_BUFFER_SIZE);
else
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
smp[i] += tmpbuf[i] * currentformants[j].amp;
oldformantamp[j] = currentformants[j].amp;
}
}

View File

@@ -31,36 +31,36 @@
class FormantFilter:public Filter_
{
public:
FormantFilter(FilterParams *pars);
~FormantFilter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency,REALTYPE q_);
void setq(REALTYPE q_);
public:
FormantFilter(FilterParams *pars);
~FormantFilter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency, REALTYPE q_);
void setq(REALTYPE q_);
void cleanup();
private:
AnalogFilter *formant[FF_MAX_FORMANTS];
REALTYPE *inbuffer,*tmpbuf;
void cleanup();
private:
AnalogFilter *formant[FF_MAX_FORMANTS];
REALTYPE *inbuffer, *tmpbuf;
struct {
REALTYPE freq,amp,q;//frequency,amplitude,Q
} formantpar[FF_MAX_VOWELS][FF_MAX_FORMANTS],currentformants[FF_MAX_FORMANTS];
struct {
REALTYPE freq, amp, q; //frequency,amplitude,Q
} formantpar[FF_MAX_VOWELS][FF_MAX_FORMANTS],
currentformants[FF_MAX_FORMANTS];
struct {
unsigned char nvowel;
} sequence [FF_MAX_SEQUENCE];
struct {
unsigned char nvowel;
} sequence [FF_MAX_SEQUENCE];
REALTYPE oldformantamp[FF_MAX_FORMANTS];
REALTYPE oldformantamp[FF_MAX_FORMANTS];
int sequencesize,numformants,firsttime;
REALTYPE oldinput,slowinput;
REALTYPE Qfactor,formantslowness,oldQfactor;
REALTYPE vowelclearness,sequencestretch;
void setpos(REALTYPE input);
int sequencesize, numformants, firsttime;
REALTYPE oldinput, slowinput;
REALTYPE Qfactor, formantslowness, oldQfactor;
REALTYPE vowelclearness, sequencestretch;
void setpos(REALTYPE input);
};

View File

@@ -24,153 +24,163 @@
#include <stdio.h>
#include "SVFilter.h"
SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages)
SVFilter::SVFilter(unsigned char Ftype,
REALTYPE Ffreq,
REALTYPE Fq,
unsigned char Fstages)
{
stages=Fstages;
type=Ftype;
freq=Ffreq;
q=Fq;
gain=1.0;
outgain=1.0;
needsinterpolation=0;
firsttime=1;
if (stages>=MAX_FILTER_STAGES) stages=MAX_FILTER_STAGES;
stages = Fstages;
type = Ftype;
freq = Ffreq;
q = Fq;
gain = 1.0;
outgain = 1.0;
needsinterpolation = 0;
firsttime = 1;
if(stages >= MAX_FILTER_STAGES)
stages = MAX_FILTER_STAGES;
cleanup();
setfreq_and_q(Ffreq,Fq);
};
setfreq_and_q(Ffreq, Fq);
}
SVFilter::~SVFilter()
{
};
{}
void SVFilter::cleanup()
{
for (int i=0;i<MAX_FILTER_STAGES+1;i++) {
st[i].low=0.0;
st[i].high=0.0;
st[i].band=0.0;
st[i].notch=0.0;
};
oldabovenq=0;
abovenq=0;
};
for(int i = 0; i < MAX_FILTER_STAGES + 1; i++) {
st[i].low = 0.0;
st[i].high = 0.0;
st[i].band = 0.0;
st[i].notch = 0.0;
}
oldabovenq = 0;
abovenq = 0;
}
void SVFilter::computefiltercoefs()
{
par.f=freq / SAMPLE_RATE*4.0;
if (par.f>0.99999) par.f=0.99999;
par.q=1.0-atan(sqrt(q))*2.0/PI;
par.q=pow(par.q,1.0/(stages+1));
par.q_sqrt=sqrt(par.q);
};
par.f = freq / SAMPLE_RATE * 4.0;
if(par.f > 0.99999)
par.f = 0.99999;
par.q = 1.0 - atan(sqrt(q)) * 2.0 / PI;
par.q = pow(par.q, 1.0 / (stages + 1));
par.q_sqrt = sqrt(par.q);
}
void SVFilter::setfreq(REALTYPE frequency)
{
if (frequency<0.1) frequency=0.1;
REALTYPE rap=freq/frequency;
if (rap<1.0) rap=1.0/rap;
if(frequency < 0.1)
frequency = 0.1;
REALTYPE rap = freq / frequency;
if(rap < 1.0)
rap = 1.0 / rap;
oldabovenq=abovenq;
abovenq=frequency>(SAMPLE_RATE/2-500.0);
oldabovenq = abovenq;
abovenq = frequency > (SAMPLE_RATE / 2 - 500.0);
int nyquistthresh=(abovenq^oldabovenq);
int nyquistthresh = (abovenq ^ oldabovenq);
if ((rap>3.0)||(nyquistthresh!=0)) {//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup)
if (firsttime==0) needsinterpolation=1;
ipar=par;
};
freq=frequency;
if((rap > 3.0) || (nyquistthresh != 0)) { //if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup)
if(firsttime == 0)
needsinterpolation = 1;
ipar = par;
}
freq = frequency;
computefiltercoefs();
firsttime=0;
firsttime = 0;
}
};
void SVFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_)
void SVFilter::setfreq_and_q(REALTYPE frequency, REALTYPE q_)
{
q=q_;
q = q_;
setfreq(frequency);
};
}
void SVFilter::setq(REALTYPE q_)
{
q=q_;
q = q_;
computefiltercoefs();
};
}
void SVFilter::settype(int type_)
{
type=type_;
type = type_;
computefiltercoefs();
};
}
void SVFilter::setgain(REALTYPE dBgain)
{
gain=dB2rap(dBgain);
gain = dB2rap(dBgain);
computefiltercoefs();
};
}
void SVFilter::setstages(int stages_)
{
if (stages_>=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1;
stages=stages_;
if(stages_ >= MAX_FILTER_STAGES)
stages_ = MAX_FILTER_STAGES - 1;
stages = stages_;
cleanup();
computefiltercoefs();
};
}
void SVFilter::singlefilterout(REALTYPE *smp,fstage &x,parameters &par)
void SVFilter::singlefilterout(REALTYPE *smp, fstage &x, parameters &par)
{
int i;
REALTYPE *out=NULL;
switch (type) {
REALTYPE *out = NULL;
switch(type) {
case 0:
out=&x.low;
out = &x.low;
break;
case 1:
out=&x.high;
out = &x.high;
break;
case 2:
out=&x.band;
out = &x.band;
break;
case 3:
out=&x.notch;
out = &x.notch;
break;
};
}
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
x.low = x.low + par.f * x.band;
x.high = par.q_sqrt * smp[i] - x.low - par.q*x.band;
x.band = par.f * x.high + x.band;
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
x.low = x.low + par.f * x.band;
x.high = par.q_sqrt * smp[i] - x.low - par.q * x.band;
x.band = par.f * x.high + x.band;
x.notch = x.high + x.low;
smp[i]= *out;
};
};
smp[i] = *out;
}
}
void SVFilter::filterout(REALTYPE *smp)
{
int i;
REALTYPE *ismp=NULL;
REALTYPE *ismp = NULL;
if (needsinterpolation!=0) {
ismp=new REALTYPE[SOUND_BUFFER_SIZE];
for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i];
for (i=0;i<stages+1;i++) singlefilterout(ismp,st[i],ipar);
};
if(needsinterpolation != 0) {
ismp = new REALTYPE[SOUND_BUFFER_SIZE];
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
ismp[i] = smp[i];
for(i = 0; i < stages + 1; i++)
singlefilterout(ismp, st[i], ipar);
}
for (i=0;i<stages+1;i++) singlefilterout(smp,st[i],par);
for(i = 0; i < stages + 1; i++)
singlefilterout(smp, st[i], par);
if (needsinterpolation!=0) {
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE;
smp[i]=ismp[i]*(1.0-x)+smp[i]*x;
};
if(needsinterpolation != 0) {
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
REALTYPE x = i / (REALTYPE) SOUND_BUFFER_SIZE;
smp[i] = ismp[i] * (1.0 - x) + smp[i] * x;
}
delete [] ismp;
needsinterpolation=0;
};
needsinterpolation = 0;
}
for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]*=outgain;
};
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
smp[i] *= outgain;
}

View File

@@ -27,40 +27,43 @@
#include "Filter_.h"
class SVFilter:public Filter_
{
public:
SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages);
~SVFilter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency,REALTYPE q_);
void setq(REALTYPE q_);
public:
SVFilter(unsigned char Ftype,
REALTYPE Ffreq,
REALTYPE Fq,
unsigned char Fstages);
~SVFilter();
void filterout(REALTYPE *smp);
void setfreq(REALTYPE frequency);
void setfreq_and_q(REALTYPE frequency, REALTYPE q_);
void setq(REALTYPE q_);
void settype(int type_);
void setgain(REALTYPE dBgain);
void setstages(int stages_);
void cleanup();
void settype(int type_);
void setgain(REALTYPE dBgain);
void setstages(int stages_);
void cleanup();
private:
struct fstage {
REALTYPE low,high,band,notch;
} st[MAX_FILTER_STAGES+1];
private:
struct fstage {
REALTYPE low, high, band, notch;
} st[MAX_FILTER_STAGES + 1];
struct parameters {
REALTYPE f,q,q_sqrt;
}par,ipar;
struct parameters {
REALTYPE f, q, q_sqrt;
} par, ipar;
void singlefilterout(REALTYPE *smp,fstage &x,parameters &par);
void computefiltercoefs();
int type;//The type of the filter (LPF1,HPF1,LPF2,HPF2...)
int stages;//how many times the filter is applied (0->1,1->2,etc.)
REALTYPE freq;//Frequency given in Hz
REALTYPE q; //Q factor (resonance or Q factor)
REALTYPE gain;//the gain of the filter (if are shelf/peak) filters
void singlefilterout(REALTYPE *smp, fstage &x, parameters &par);
void computefiltercoefs();
int type; //The type of the filter (LPF1,HPF1,LPF2,HPF2...)
int stages; //how many times the filter is applied (0->1,1->2,etc.)
REALTYPE freq; //Frequency given in Hz
REALTYPE q; //Q factor (resonance or Q factor)
REALTYPE gain; //the gain of the filter (if are shelf/peak) filters
int abovenq;//this is 1 if the frequency is above the nyquist
int oldabovenq;
int needsinterpolation,firsttime;
int abovenq; //this is 1 if the frequency is above the nyquist
int oldabovenq;
int needsinterpolation, firsttime;
};

View File

@@ -0,0 +1,192 @@
/*
ZynAddSubFX - a software synthesizer
Unison.cpp - Unison effect (multivoice chorus)
Copyright (C) 2002-2009 Nasca Octavian Paul
Author: Nasca Octavian Paul
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 <math.h>
#include <stdio.h>
#include "Unison.h"
Unison::Unison(int update_period_samples_, REALTYPE max_delay_sec_) {
update_period_samples = update_period_samples_;
max_delay = (int)(max_delay_sec_ * (REALTYPE)SAMPLE_RATE + 1);
if(max_delay < 10)
max_delay = 10;
delay_buffer = new REALTYPE[max_delay];
delay_k = 0;
base_freq = 1.0;
unison_bandwidth_cents = 10.0;
ZERO_REALTYPE(delay_buffer, max_delay);
uv = NULL;
update_period_sample_k = 0;
first_time = 0;
set_size(1);
}
Unison::~Unison() {
delete [] delay_buffer;
if(uv)
delete [] uv;
}
void Unison::set_size(int new_size) {
if(new_size < 1)
new_size = 1;
unison_size = new_size;
if(uv)
delete [] uv;
uv = new UnisonVoice[unison_size];
first_time = true;
update_parameters();
}
void Unison::set_base_frequency(REALTYPE freq) {
base_freq = freq;
update_parameters();
}
void Unison::set_bandwidth(REALTYPE bandwidth) {
if(bandwidth < 0)
bandwidth = 0.0;
if(bandwidth > 1200.0)
bandwidth = 1200.0;
printf("bandwidth %g\n", bandwidth);
#warning \
: todo: if bandwidth is too small the audio will be self canceled (because of the sign change of the outputs)
unison_bandwidth_cents = bandwidth;
update_parameters();
}
void Unison::update_parameters() {
if(!uv)
return;
REALTYPE increments_per_second = SAMPLE_RATE
/ (REALTYPE) update_period_samples;
// printf("#%g, %g\n",increments_per_second,base_freq);
for(int i = 0; i < unison_size; i++) {
REALTYPE base = pow(UNISON_FREQ_SPAN, RND * 2.0 - 1.0);
uv[i].relative_amplitude = base;
REALTYPE period = base / base_freq;
REALTYPE m = 4.0 / (period * increments_per_second);
if(RND < 0.5)
m = -m;
uv[i].step = m;
// printf("%g %g\n",uv[i].relative_amplitude,period);
}
REALTYPE max_speed = pow(2.0, unison_bandwidth_cents / 1200.0);
unison_amplitude_samples = 0.125
* (max_speed - 1.0) * SAMPLE_RATE / base_freq;
printf("unison_amplitude_samples %g\n", unison_amplitude_samples);
#warning \
todo: test if unison_amplitude_samples is to big and reallocate bigger memory
if(unison_amplitude_samples >= max_delay - 1)
unison_amplitude_samples = max_delay - 2;
update_unison_data();
}
void Unison::process(int bufsize, REALTYPE *inbuf, REALTYPE *outbuf) {
if(!uv)
return;
if(!outbuf)
outbuf = inbuf;
REALTYPE volume = 1.0 / sqrt(unison_size);
REALTYPE xpos_step = 1.0 / (REALTYPE) update_period_samples;
REALTYPE xpos = (REALTYPE) update_period_sample_k * xpos_step;
for(int i = 0; i < bufsize; i++) {
if((update_period_sample_k++) >= update_period_samples) {
update_unison_data();
update_period_sample_k = 0;
xpos = 0.0;
}
xpos += xpos_step;
REALTYPE in = inbuf[i], out = 0.0;
REALTYPE sign = 1.0;
for(int k = 0; k < unison_size; k++) {
REALTYPE vpos = uv[k].realpos1
* (1.0 - xpos) + uv[k].realpos2 * xpos; //optimize
REALTYPE pos = delay_k + max_delay - vpos - 1.0; //optimize
int posi;
REALTYPE posf;
F2I(pos, posi); //optimize!
if(posi >= max_delay)
posi -= max_delay;
posf = pos - floor(pos);
out +=
((1.0
- posf) * delay_buffer[posi] + posf
* delay_buffer[posi + 1]) * sign;
sign = -sign;
}
outbuf[i] = out * volume;
// printf("%d %g\n",i,outbuf[i]);
delay_buffer[delay_k] = in;
if((++delay_k) >= max_delay)
delay_k = 0;
}
}
void Unison::update_unison_data() {
if(!uv)
return;
for(int k = 0; k < unison_size; k++) {
REALTYPE pos = uv[k].position;
REALTYPE step = uv[k].step;
pos += step;
if(pos <= -1.0) {
pos = -1.0;
step = -step;
}
if(pos >= 1.0) {
pos = 1.0;
step = -step;
}
REALTYPE vibratto_val = (pos - 0.333333333 * pos * pos * pos) * 1.5; //make the vibratto lfo smoother
#warning \
I will use relative amplitude, so the delay might be bigger than the whole buffer
#warning \
I have to enlarge (reallocate) the buffer to make place for the whole delay
REALTYPE newval = 1.0 + 0.5
* (vibratto_val
+ 1.0) * unison_amplitude_samples
* uv[k].relative_amplitude;
if(first_time)
uv[k].realpos1 = uv[k].realpos2 = newval;
else{
uv[k].realpos1 = uv[k].realpos2;
uv[k].realpos2 = newval;
}
uv[k].position = pos;
uv[k].step = step;
}
if(first_time)
first_time = false;
}

View File

@@ -0,0 +1,69 @@
/*
ZynAddSubFX - a software synthesizer
Unison.h - Unison effect (multivoice chorus)
Copyright (C) 2002-2009 Nasca Octavian Paul
Author: Nasca Octavian Paul
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 UNISON_H
#define UNISON_H
#include <stdlib.h>
#include "../globals.h"
#define UNISON_FREQ_SPAN 2.0
//how much the unison frequencies varies (always >= 1.0)
class Unison
{
public:
Unison(int update_period_samples_, REALTYPE max_delay_sec_);
~Unison();
void set_size(int new_size);
void set_base_frequency(REALTYPE freq);
void set_bandwidth(REALTYPE bandwidth_cents);
void process(int bufsize, REALTYPE *inbuf, REALTYPE *outbuf = NULL);
private:
void update_parameters();
void update_unison_data();
int unison_size;
REALTYPE base_freq;
struct UnisonVoice {
REALTYPE step, position; //base LFO
REALTYPE realpos1, realpos2; //the position regarding samples
REALTYPE relative_amplitude;
REALTYPE lin_fpos, lin_ffreq;
UnisonVoice() {
position = RND * 1.8 - 0.9;
realpos1 = 0.0;
realpos2 = 0.0;
step = 0.0;
relative_amplitude = 1.0;
}
} *uv;
int update_period_samples, update_period_sample_k;
int max_delay, delay_k;
bool first_time;
REALTYPE *delay_buffer;
REALTYPE unison_amplitude_samples;
REALTYPE unison_bandwidth_cents;
};
#endif

View File

@@ -23,83 +23,87 @@
#include <cmath>
#include "Alienwah.h"
Alienwah::Alienwah(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_)
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL)
Alienwah::Alienwah(const int &insertion_,
REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), oldl(NULL), oldr(NULL)
{
setpreset(Ppreset);
cleanup();
oldclfol=complex<REALTYPE>(fb,0.0);
oldclfor=complex<REALTYPE>(fb,0.0);
};
oldclfol = complex<REALTYPE>(fb, 0.0);
oldclfor = complex<REALTYPE>(fb, 0.0);
}
Alienwah::~Alienwah()
{
if (oldl!=NULL) delete [] oldl;
if (oldr!=NULL) delete [] oldr ;
};
if(oldl != NULL)
delete [] oldl;
if(oldr != NULL)
delete [] oldr;
}
/*
* Apply the effect
*/
void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr)
void Alienwah::out(REALTYPE *smpsl, REALTYPE *smpsr)
{
REALTYPE lfol,lfor; //Left/Right LFOs
complex<REALTYPE> clfol,clfor,out,tmp;
REALTYPE lfol, lfor; //Left/Right LFOs
complex<REALTYPE> clfol, clfor, out, tmp;
/**\todo Rework, as optimization can be used when the new complex type is
* utilized.
* Before all calculations needed to be done with individual REALTYPE,
* but now they can be done together*/
lfo.effectlfoout(&lfol,&lfor);
lfol*=depth*PI*2.0;
lfor*=depth*PI*2.0;
clfol=complex<REALTYPE>(cos(lfol+phase)*fb,sin(lfol+phase)*fb); //rework
clfor=complex<REALTYPE>(cos(lfor+phase)*fb,sin(lfor+phase)*fb); //rework
lfo.effectlfoout(&lfol, &lfor);
lfol *= depth * PI * 2.0;
lfor *= depth * PI * 2.0;
clfol = complex<REALTYPE>(cos(lfol + phase) * fb, sin(lfol + phase) * fb); //rework
clfor = complex<REALTYPE>(cos(lfor + phase) * fb, sin(lfor + phase) * fb); //rework
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
REALTYPE x=((REALTYPE) i)/SOUND_BUFFER_SIZE;
REALTYPE x1=1.0-x;
for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
REALTYPE x = ((REALTYPE) i) / SOUND_BUFFER_SIZE;
REALTYPE x1 = 1.0 - x;
//left
tmp=clfol*x+oldclfol*x1;
tmp = clfol * x + oldclfol * x1;
out=tmp*oldl[oldk];
out.real()+=(1-fabs(fb))*smpsr[i]*(1.0-panning);
out = tmp * oldl[oldk];
out.real() += (1 - fabs(fb)) * smpsr[i] * (1.0 - panning);
oldl[oldk]=out;
REALTYPE l=out.real()*10.0*(fb+0.1);
oldl[oldk] = out;
REALTYPE l = out.real() * 10.0 * (fb + 0.1);
//right
tmp=clfor*x+oldclfor*x1;
tmp = clfor * x + oldclfor * x1;
out=tmp*oldr[oldk];
out.real()+=(1-fabs(fb))*smpsr[i]*(1.0-panning);
out = tmp * oldr[oldk];
out.real() += (1 - fabs(fb)) * smpsr[i] * (1.0 - panning);
oldr[oldk]=out;
REALTYPE r=out.real()*10.0*(fb+0.1);
oldr[oldk] = out;
REALTYPE r = out.real() * 10.0 * (fb + 0.1);
if (++oldk>=Pdelay) oldk=0;
if(++oldk >= Pdelay)
oldk = 0;
//LRcross
efxoutl[i]=l*(1.0-lrcross)+r*lrcross;
efxoutr[i]=r*(1.0-lrcross)+l*lrcross;
};
efxoutl[i] = l * (1.0 - lrcross) + r * lrcross;
efxoutr[i] = r * (1.0 - lrcross) + l * lrcross;
}
oldclfol=clfol;
oldclfor=clfor;
};
oldclfol = clfol;
oldclfor = clfor;
}
/*
* Cleanup the effect
*/
void Alienwah::cleanup()
{
for (int i=0;i<Pdelay;i++) {
oldl[i]=complex<REALTYPE>(0.0,0.0);
oldr[i]=complex<REALTYPE>(0.0,0.0);
};
oldk=0;
};
for(int i = 0; i < Pdelay; i++) {
oldl[i] = complex<REALTYPE>(0.0, 0.0);
oldr[i] = complex<REALTYPE>(0.0, 0.0);
}
oldk = 0;
}
/*
@@ -108,81 +112,92 @@ void Alienwah::cleanup()
void Alienwah::setdepth(const unsigned char &Pdepth)
{
this->Pdepth=Pdepth;
depth=(Pdepth/127.0);
};
this->Pdepth = Pdepth;
depth = (Pdepth / 127.0);
}
void Alienwah::setfb(const unsigned char &Pfb)
{
this->Pfb=Pfb;
fb=fabs((Pfb-64.0)/64.1);
fb=sqrt(fb);
if (fb<0.4) fb=0.4;
if (Pfb<64) fb=-fb;
};
this->Pfb = Pfb;
fb = fabs((Pfb - 64.0) / 64.1);
fb = sqrt(fb);
if(fb < 0.4)
fb = 0.4;
if(Pfb < 64)
fb = -fb;
}
void Alienwah::setvolume(const unsigned char &Pvolume)
{
this->Pvolume=Pvolume;
outvolume=Pvolume/127.0;
if (insertion==0) volume=1.0;
else volume=outvolume;
};
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
if(insertion == 0)
volume = 1.0;
else
volume = outvolume;
}
void Alienwah::setpanning(const unsigned char &Ppanning)
{
this->Ppanning=Ppanning;
panning=Ppanning/127.0;
};
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
void Alienwah::setlrcross(const unsigned char &Plrcross)
{
this->Plrcross=Plrcross;
lrcross=Plrcross/127.0;
};
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0;
}
void Alienwah::setphase(const unsigned char &Pphase)
{
this->Pphase=Pphase;
phase=(Pphase-64.0)/64.0*PI;
};
this->Pphase = Pphase;
phase = (Pphase - 64.0) / 64.0 * PI;
}
void Alienwah::setdelay(const unsigned char &Pdelay)
{
if (oldl!=NULL) delete [] oldl;
if (oldr!=NULL) delete [] oldr;
if (Pdelay>=MAX_ALIENWAH_DELAY) this->Pdelay=MAX_ALIENWAH_DELAY;
else this->Pdelay=Pdelay;
oldl=new complex<REALTYPE>[Pdelay];
oldr=new complex<REALTYPE>[Pdelay];
if(oldl != NULL)
delete [] oldl;
if(oldr != NULL)
delete [] oldr;
if(Pdelay >= MAX_ALIENWAH_DELAY)
this->Pdelay = MAX_ALIENWAH_DELAY;
else
this->Pdelay = Pdelay;
oldl = new complex<REALTYPE>[Pdelay];
oldr = new complex<REALTYPE>[Pdelay];
cleanup();
};
}
void Alienwah::setpreset(unsigned char npreset)
{
const int PRESET_SIZE=11;
const int NUM_PRESETS=4;
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
const int PRESET_SIZE = 11;
const int NUM_PRESETS = 4;
unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
//AlienWah1
{127,64,70,0,0,62,60,105,25,0,64},
{127, 64, 70, 0, 0, 62, 60, 105, 25, 0, 64},
//AlienWah2
{127,64,73,106,0,101,60,105,17,0,64},
{127, 64, 73, 106, 0, 101, 60, 105, 17, 0, 64},
//AlienWah3
{127,64,63,0,1,100,112,105,31,0,42},
{127, 64, 63, 0, 1, 100, 112, 105, 31, 0, 42},
//AlienWah4
{93,64,25,0,1,66,101,11,47,0,86}
{93, 64, 25, 0, 1, 66, 101, 11, 47, 0, 86}
};
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
if (insertion==0) changepar(0,presets[npreset][0]/2);//lower the volume if this is system effect
Ppreset=npreset;
};
if(npreset >= NUM_PRESETS)
npreset = NUM_PRESETS - 1;
for(int n = 0; n < PRESET_SIZE; n++)
changepar(n, presets[npreset][n]);
if(insertion == 0)
changepar(0, presets[npreset][0] / 2); //lower the volume if this is system effect
Ppreset = npreset;
}
void Alienwah::changepar(const int &npar,const unsigned char &value)
void Alienwah::changepar(const int &npar, const unsigned char &value)
{
switch (npar) {
switch(npar) {
case 0:
setvolume(value);
break;
@@ -190,19 +205,19 @@ void Alienwah::changepar(const int &npar,const unsigned char &value)
setpanning(value);
break;
case 2:
lfo.Pfreq=value;
lfo.Pfreq = value;
lfo.updateparams();
break;
case 3:
lfo.Prandomness=value;
lfo.Prandomness = value;
lfo.updateparams();
break;
case 4:
lfo.PLFOtype=value;
lfo.PLFOtype = value;
lfo.updateparams();
break;
case 5:
lfo.Pstereo=value;
lfo.Pstereo = value;
lfo.updateparams();
break;
case 6:
@@ -220,48 +235,47 @@ void Alienwah::changepar(const int &npar,const unsigned char &value)
case 10:
setphase(value);
break;
};
};
}
}
unsigned char Alienwah::getpar(const int &npar)const
unsigned char Alienwah::getpar(const int &npar) const
{
switch (npar) {
switch(npar) {
case 0:
return(Pvolume);
return Pvolume;
break;
case 1:
return(Ppanning);
return Ppanning;
break;
case 2:
return(lfo.Pfreq);
return lfo.Pfreq;
break;
case 3:
return(lfo.Prandomness);
return lfo.Prandomness;
break;
case 4:
return(lfo.PLFOtype);
return lfo.PLFOtype;
break;
case 5:
return(lfo.Pstereo);
return lfo.Pstereo;
break;
case 6:
return(Pdepth);
return Pdepth;
break;
case 7:
return(Pfb);
return Pfb;
break;
case 8:
return(Pdelay);
return Pdelay;
break;
case 9:
return(Plrcross);
return Plrcross;
break;
case 10:
return(Pphase);
return Pphase;
break;
default:
return (0);
};
};
return 0;
}
}

View File

@@ -34,49 +34,51 @@ using namespace std;
/**"AlienWah" Effect*/
class Alienwah:public Effect
{
public:
/**
* Constructor
* @param insetion_ 1 for insertion Effect, 0 for others
* @param efxoutl_ Pointer to Alienwah's left channel output buffer
* @param efxoutr_ Pointer to Alienwah's left channel output buffer
* @return Initialized Alienwah
*/
Alienwah(const int &insetion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_);
~Alienwah();
void out(REALTYPE *const smpsl,REALTYPE *const smpsr);
public:
/**
* Constructor
* @param insetion_ 1 for insertion Effect, 0 for others
* @param efxoutl_ Pointer to Alienwah's left channel output buffer
* @param efxoutr_ Pointer to Alienwah's left channel output buffer
* @return Initialized Alienwah
*/
Alienwah(const int &insetion_,
REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_);
~Alienwah();
void out(REALTYPE *const smpsl, REALTYPE *const smpsr);
void setpreset(unsigned char npreset);
void changepar(const int &npar,const unsigned char &value);
unsigned char getpar(const int &npar)const;
void cleanup();
void setpreset(unsigned char npreset);
void changepar(const int &npar, const unsigned char &value);
unsigned char getpar(const int &npar) const;
void cleanup();
private:
//Alienwah Parameters
EffectLFO lfo;//lfo-ul Alienwah
unsigned char Pvolume;
unsigned char Ppanning;
unsigned char Pdepth;//the depth of the Alienwah
unsigned char Pfb;//feedback
unsigned char Plrcross;//feedback
unsigned char Pdelay;
unsigned char Pphase;
private:
//Alienwah Parameters
EffectLFO lfo; //lfo-ul Alienwah
unsigned char Pvolume;
unsigned char Ppanning;
unsigned char Pdepth; //the depth of the Alienwah
unsigned char Pfb; //feedback
unsigned char Plrcross; //feedback
unsigned char Pdelay;
unsigned char Pphase;
//Control Parameters
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setdepth(const unsigned char &Pdepth);
void setfb(const unsigned char &Pfb);
void setlrcross(const unsigned char &Plrcross);
void setdelay(const unsigned char &Pdelay);
void setphase(const unsigned char &Pphase);
//Control Parameters
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setdepth(const unsigned char &Pdepth);
void setfb(const unsigned char &Pfb);
void setlrcross(const unsigned char &Plrcross);
void setdelay(const unsigned char &Pdelay);
void setphase(const unsigned char &Pphase);
//Internal Values
REALTYPE panning,fb,depth,lrcross,phase;
complex<REALTYPE> *oldl,*oldr;
complex<REALTYPE> oldclfol,oldclfor;
int oldk;
//Internal Values
REALTYPE panning, fb, depth, lrcross, phase;
complex<REALTYPE> *oldl, *oldr;
complex<REALTYPE> oldclfol, oldclfor;
int oldk;
};
#endif

View File

@@ -26,26 +26,28 @@
using namespace std;
Chorus::Chorus(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_)
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0),
maxdelay((int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE)),
delaySample(maxdelay)
Chorus::Chorus(const int &insertion_,
REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
maxdelay((int)(MAX_CHORUS_DELAY / 1000.0 * SAMPLE_RATE)),
delaySample(maxdelay)
{
dlk=0;
drk=0;
dlk = 0;
drk = 0;
//maxdelay=(int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE);
//delayl=new REALTYPE[maxdelay];
//delayr=new REALTYPE[maxdelay];
setpreset(Ppreset);
lfo.effectlfoout(&lfol,&lfor);
dl2=getdelay(lfol);
dr2=getdelay(lfor);
lfo.effectlfoout(&lfol, &lfor);
dl2 = getdelay(lfol);
dr2 = getdelay(lfor);
cleanup();
};
}
Chorus::~Chorus() {};
Chorus::~Chorus() {}
/*
* get the delay value in samples; xlfo is the current lfo value
@@ -53,91 +55,100 @@ Chorus::~Chorus() {};
REALTYPE Chorus::getdelay(REALTYPE xlfo)
{
REALTYPE result;
if (Pflangemode==0) {
result=(delay+xlfo*depth)*SAMPLE_RATE;
} else result=0;
if(Pflangemode == 0)
result = (delay + xlfo * depth) * SAMPLE_RATE;
else
result = 0;
//check if it is too big delay(caused bu errornous setdelay() and setdepth()
/**\todo fix setdelay() and setdepth(), so this error cannot occur*/
if ((result+0.5)>=maxdelay) {
cerr << "WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n";
result=maxdelay-1.0;
};
return(result);
};
if((result + 0.5) >= maxdelay) {
cerr
<<
"WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n";
result = maxdelay - 1.0;
}
return result;
}
/*
* Apply the effect
*/
void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr)
void Chorus::out(REALTYPE *smpsl, REALTYPE *smpsr)
{
const Stereo<AuSample> input(AuSample(SOUND_BUFFER_SIZE,smpsl),AuSample(SOUND_BUFFER_SIZE,smpsr));
const Stereo<AuSample> input(AuSample(SOUND_BUFFER_SIZE, smpsl), AuSample(
SOUND_BUFFER_SIZE,
smpsr));
out(input);
}
void Chorus::out(const Stereo<AuSample> &input)
{
const REALTYPE one=1.0;
dl1=dl2;
dr1=dr2;
lfo.effectlfoout(&lfol,&lfor);
const REALTYPE one = 1.0;
dl1 = dl2;
dr1 = dr2;
lfo.effectlfoout(&lfol, &lfor);
dl2=getdelay(lfol);
dr2=getdelay(lfor);
dl2 = getdelay(lfol);
dr2 = getdelay(lfor);
for (int i=0;i<input.l().size();i++) {
REALTYPE inl=input.l()[i];
REALTYPE inr=input.r()[i];
for(int i = 0; i < input.l().size(); i++) {
REALTYPE inl = input.l()[i];
REALTYPE inr = input.r()[i];
//LRcross
Stereo<REALTYPE> tmpc(inl,inr);
Stereo<REALTYPE> tmpc(inl, inr);
//REALTYPE r=inr;
inl=tmpc.l()*(1.0-lrcross)+tmpc.r()*lrcross;
inr=tmpc.r()*(1.0-lrcross)+tmpc.l()*lrcross;
inl = tmpc.l() * (1.0 - lrcross) + tmpc.r() * lrcross;
inr = tmpc.r() * (1.0 - lrcross) + tmpc.l() * lrcross;
//Left channel
//compute the delay in samples using linear interpolation between the lfo delays
mdel=(dl1*(SOUND_BUFFER_SIZE-i)+dl2*i)/SOUND_BUFFER_SIZE;
if (++dlk>=maxdelay) dlk=0;
REALTYPE tmp=dlk-mdel+maxdelay*2.0;//where should I get the sample from
mdel = (dl1 * (SOUND_BUFFER_SIZE - i) + dl2 * i) / SOUND_BUFFER_SIZE;
if(++dlk >= maxdelay)
dlk = 0;
REALTYPE tmp = dlk - mdel + maxdelay * 2.0; //where should I get the sample from
F2I(tmp,dlhi);
dlhi%=maxdelay;
F2I(tmp, dlhi);
dlhi %= maxdelay;
dlhi2=(dlhi-1+maxdelay)%maxdelay;
dllo=1.0-fmod(tmp,one);
efxoutl[i]=delaySample.l()[dlhi2]*dllo+delaySample.l()[dlhi]*(1.0-dllo);
delaySample.l()[dlk]=inl+efxoutl[i]*fb;
dlhi2 = (dlhi - 1 + maxdelay) % maxdelay;
dllo = 1.0 - fmod(tmp, one);
efxoutl[i] = delaySample.l()[dlhi2] * dllo + delaySample.l()[dlhi]
* (1.0 - dllo);
delaySample.l()[dlk] = inl + efxoutl[i] * fb;
//Right channel
//compute the delay in samples using linear interpolation between the lfo delays
mdel=(dr1*(SOUND_BUFFER_SIZE-i)+dr2*i)/SOUND_BUFFER_SIZE;
if (++drk>=maxdelay) drk=0;
tmp=drk*1.0-mdel+maxdelay*2.0;//where should I get the sample from
mdel = (dr1 * (SOUND_BUFFER_SIZE - i) + dr2 * i) / SOUND_BUFFER_SIZE;
if(++drk >= maxdelay)
drk = 0;
tmp = drk * 1.0 - mdel + maxdelay * 2.0; //where should I get the sample from
F2I(tmp,dlhi);
dlhi%=maxdelay;
F2I(tmp, dlhi);
dlhi %= maxdelay;
dlhi2=(dlhi-1+maxdelay)%maxdelay;
dllo=1.0-fmod(tmp,one);
efxoutr[i]=delaySample.r()[dlhi2]*dllo+delaySample.r()[dlhi]*(1.0-dllo);
delaySample.r()[dlk]=inr+efxoutr[i]*fb;
dlhi2 = (dlhi - 1 + maxdelay) % maxdelay;
dllo = 1.0 - fmod(tmp, one);
efxoutr[i] = delaySample.r()[dlhi2] * dllo + delaySample.r()[dlhi]
* (1.0 - dllo);
delaySample.r()[dlk] = inr + efxoutr[i] * fb;
}
};
if (Poutsub!=0)
for (int i=0;i<input.l().size();i++) {
if(Poutsub != 0)
for(int i = 0; i < input.l().size(); i++) {
efxoutl[i] *= -1.0;
efxoutr[i] *= -1.0;
};
}
;
for (int i=0;i<input.l().size();i++) {
efxoutl[i]*=panning;
efxoutr[i]*=(1.0-panning);
};
};
for(int i = 0; i < input.l().size(); i++) {
efxoutl[i] *= panning;
efxoutr[i] *= (1.0 - panning);
}
}
/*
* Cleanup the effect
@@ -146,84 +157,88 @@ void Chorus::cleanup()
{
delaySample.l().clear();
delaySample.r().clear();
};
}
/*
* Parameter control
*/
void Chorus::setdepth(const unsigned char &Pdepth)
{
this->Pdepth=Pdepth;
depth=(pow(8.0,(Pdepth/127.0)*2.0)-1.0)/1000.0;//seconds
};
this->Pdepth = Pdepth;
depth = (pow(8.0, (Pdepth / 127.0) * 2.0) - 1.0) / 1000.0; //seconds
}
void Chorus::setdelay(const unsigned char &Pdelay)
{
this->Pdelay=Pdelay;
delay=(pow(10.0,(Pdelay/127.0)*2.0)-1.0)/1000.0;//seconds
};
this->Pdelay = Pdelay;
delay = (pow(10.0, (Pdelay / 127.0) * 2.0) - 1.0) / 1000.0; //seconds
}
void Chorus::setfb(const unsigned char &Pfb)
{
this->Pfb=Pfb;
fb=(Pfb-64.0)/64.1;
};
this->Pfb = Pfb;
fb = (Pfb - 64.0) / 64.1;
}
void Chorus::setvolume(const unsigned char &Pvolume)
{
this->Pvolume=Pvolume;
outvolume=Pvolume/127.0;
if (insertion==0) volume=1.0;
else volume=outvolume;
};
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
if(insertion == 0)
volume = 1.0;
else
volume = outvolume;
}
void Chorus::setpanning(const unsigned char &Ppanning)
{
this->Ppanning=Ppanning;
panning=Ppanning/127.0;
};
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
void Chorus::setlrcross(const unsigned char &Plrcross)
{
this->Plrcross=Plrcross;
lrcross=Plrcross/127.0;
};
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0;
}
void Chorus::setpreset(unsigned char npreset)
{
const int PRESET_SIZE=12;
const int NUM_PRESETS=10;
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
const int PRESET_SIZE = 12;
const int NUM_PRESETS = 10;
unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
//Chorus1
{64,64,50,0,0,90,40,85,64,119,0,0},
{64, 64, 50, 0, 0, 90, 40, 85, 64, 119, 0, 0 },
//Chorus2
{64,64,45,0,0,98,56,90,64,19,0,0},
{64, 64, 45, 0, 0, 98, 56, 90, 64, 19, 0, 0 },
//Chorus3
{64,64,29,0,1,42,97,95,90,127,0,0},
{64, 64, 29, 0, 1, 42, 97, 95, 90, 127, 0, 0 },
//Celeste1
{64,64,26,0,0,42,115,18,90,127,0,0},
{64, 64, 26, 0, 0, 42, 115, 18, 90, 127, 0, 0 },
//Celeste2
{64,64,29,117,0,50,115,9,31,127,0,1},
{64, 64, 29, 117, 0, 50, 115, 9, 31, 127, 0, 1 },
//Flange1
{64,64,57,0,0,60,23,3,62,0,0,0},
{64, 64, 57, 0, 0, 60, 23, 3, 62, 0, 0, 0 },
//Flange2
{64,64,33,34,1,40,35,3,109,0,0,0},
{64, 64, 33, 34, 1, 40, 35, 3, 109, 0, 0, 0 },
//Flange3
{64,64,53,34,1,94,35,3,54,0,0,1},
{64, 64, 53, 34, 1, 94, 35, 3, 54, 0, 0, 1 },
//Flange4
{64,64,40,0,1,62,12,19,97,0,0,0},
{64, 64, 40, 0, 1, 62, 12, 19, 97, 0, 0, 0 },
//Flange5
{64,64,55,105,0,24,39,19,17,0,0,1}
{64, 64, 55, 105, 0, 24, 39, 19, 17, 0, 0, 1 }
};
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
Ppreset=npreset;
};
if(npreset >= NUM_PRESETS)
npreset = NUM_PRESETS - 1;
for(int n = 0; n < PRESET_SIZE; n++)
changepar(n, presets[npreset][n]);
Ppreset = npreset;
}
void Chorus::changepar(const int &npar,const unsigned char &value)
void Chorus::changepar(const int &npar, const unsigned char &value)
{
switch (npar) {
switch(npar) {
case 0:
setvolume(value);
break;
@@ -231,19 +246,19 @@ void Chorus::changepar(const int &npar,const unsigned char &value)
setpanning(value);
break;
case 2:
lfo.Pfreq=value;
lfo.Pfreq = value;
lfo.updateparams();
break;
case 3:
lfo.Prandomness=value;
lfo.Prandomness = value;
lfo.updateparams();
break;
case 4:
lfo.PLFOtype=value;
lfo.PLFOtype = value;
lfo.updateparams();
break;
case 5:
lfo.Pstereo=value;
lfo.Pstereo = value;
lfo.updateparams();
break;
case 6:
@@ -259,58 +274,61 @@ void Chorus::changepar(const int &npar,const unsigned char &value)
setlrcross(value);
break;
case 10:
if (value>1) Pflangemode=1;
else Pflangemode=value;
if(value > 1)
Pflangemode = 1;
else
Pflangemode = value;
break;
case 11:
if (value>1) Poutsub=1;
else Poutsub=value;
if(value > 1)
Poutsub = 1;
else
Poutsub = value;
break;
};
};
}
}
unsigned char Chorus::getpar(const int &npar)const
unsigned char Chorus::getpar(const int &npar) const
{
switch (npar) {
switch(npar) {
case 0:
return(Pvolume);
return Pvolume;
break;
case 1:
return(Ppanning);
return Ppanning;
break;
case 2:
return(lfo.Pfreq);
return lfo.Pfreq;
break;
case 3:
return(lfo.Prandomness);
return lfo.Prandomness;
break;
case 4:
return(lfo.PLFOtype);
return lfo.PLFOtype;
break;
case 5:
return(lfo.Pstereo);
return lfo.Pstereo;
break;
case 6:
return(Pdepth);
return Pdepth;
break;
case 7:
return(Pdelay);
return Pdelay;
break;
case 8:
return(Pfb);
return Pfb;
break;
case 9:
return(Plrcross);
return Plrcross;
break;
case 10:
return(Pflangemode);
return Pflangemode;
break;
case 11:
return(Poutsub);
return Poutsub;
break;
default:
return (0);
};
};
return 0;
}
}

View File

@@ -33,83 +33,83 @@
/**Chorus and Flange effects*/
class Chorus:public Effect
{
public:
Chorus(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
/**Destructor*/
~Chorus();
void out(REALTYPE *smpsl,REALTYPE *smpsr);
void out(const Stereo<AuSample> &input);
void setpreset(unsigned char npreset);
/**
* Sets the value of the chosen variable
*
* The possible parameters are:
* -# Volume
* -# Panning
* -# LFO Frequency
* -# LFO Randomness
* -# LFO Type
* -# LFO stereo
* -# Depth
* -# Delay
* -# Feedback
* -# Flange Mode
* -# Subtractive
* @param npar number of chosen parameter
* @param value the new value
*/
void changepar(const int &npar,const unsigned char &value);
/**
* Gets the value of the chosen variable
*
* The possible parameters are:
* -# Volume
* -# Panning
* -# LFO Frequency
* -# LFO Randomness
* -# LFO Type
* -# LFO stereo
* -# Depth
* -# Delay
* -# Feedback
* -# Flange Mode
* -# Subtractive
* @param npar number of chosen parameter
* @return the value of the parameter
*/
unsigned char getpar(const int &npar)const;
void cleanup();
public:
Chorus(const int &insetion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
/**Destructor*/
~Chorus();
void out(REALTYPE *smpsl, REALTYPE *smpsr);
void out(const Stereo<AuSample> &input);
void setpreset(unsigned char npreset);
/**
* Sets the value of the chosen variable
*
* The possible parameters are:
* -# Volume
* -# Panning
* -# LFO Frequency
* -# LFO Randomness
* -# LFO Type
* -# LFO stereo
* -# Depth
* -# Delay
* -# Feedback
* -# Flange Mode
* -# Subtractive
* @param npar number of chosen parameter
* @param value the new value
*/
void changepar(const int &npar, const unsigned char &value);
/**
* Gets the value of the chosen variable
*
* The possible parameters are:
* -# Volume
* -# Panning
* -# LFO Frequency
* -# LFO Randomness
* -# LFO Type
* -# LFO stereo
* -# Depth
* -# Delay
* -# Feedback
* -# Flange Mode
* -# Subtractive
* @param npar number of chosen parameter
* @return the value of the parameter
*/
unsigned char getpar(const int &npar) const;
void cleanup();
private:
//Chorus Parameters
EffectLFO lfo;//lfo-ul chorus
unsigned char Pvolume;
unsigned char Ppanning;
unsigned char Pdepth;//the depth of the Chorus(ms)
unsigned char Pdelay;//the delay (ms)
unsigned char Pfb;//feedback
unsigned char Plrcross;//feedback
unsigned char Pflangemode;//how the LFO is scaled, to result chorus or flange
unsigned char Poutsub;//if I wish to substract the output instead of the adding it
private:
//Chorus Parameters
EffectLFO lfo; //lfo-ul chorus
unsigned char Pvolume;
unsigned char Ppanning;
unsigned char Pdepth; //the depth of the Chorus(ms)
unsigned char Pdelay; //the delay (ms)
unsigned char Pfb; //feedback
unsigned char Plrcross; //feedback
unsigned char Pflangemode; //how the LFO is scaled, to result chorus or flange
unsigned char Poutsub; //if I wish to substract the output instead of the adding it
//Parameter Controls
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setdepth(const unsigned char &Pdepth);
void setdelay(const unsigned char &Pdelay);
void setfb(const unsigned char &Pfb);
void setlrcross(const unsigned char &Plrcross);
//Parameter Controls
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setdepth(const unsigned char &Pdepth);
void setdelay(const unsigned char &Pdelay);
void setfb(const unsigned char &Pfb);
void setlrcross(const unsigned char &Plrcross);
//Internal Values
REALTYPE depth,delay,fb,lrcross,panning;
REALTYPE dl1,dl2,dr1,dr2,lfol,lfor;
int maxdelay;
Stereo<AuSample> delaySample;
//REALTYPE *delayl,*delayr;
int dlk,drk,dlhi,dlhi2;
REALTYPE getdelay(REALTYPE xlfo);
REALTYPE dllo,mdel;
//Internal Values
REALTYPE depth, delay, fb, lrcross, panning;
REALTYPE dl1, dl2, dr1, dr2, lfol, lfor;
int maxdelay;
Stereo<AuSample> delaySample;
//REALTYPE *delayl,*delayr;
int dlk, drk, dlhi, dlhi2;
REALTYPE getdelay(REALTYPE xlfo);
REALTYPE dllo, mdel;
};
#endif

View File

@@ -28,159 +28,199 @@
* Waveshape (this is called by OscilGen::waveshape and Distorsion::process)
*/
void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive)
void waveshapesmps(int n,
REALTYPE *smps,
unsigned char type,
unsigned char drive)
{
int i;
REALTYPE ws=drive/127.0;
int i;
REALTYPE ws = drive / 127.0;
REALTYPE tmpv;
switch (type) {
switch(type) {
case 1:
ws=pow(10,ws*ws*3.0)-1.0+0.001;//Arctangent
for (i=0;i<n;i++)
smps[i]=atan(smps[i]*ws)/atan(ws);
ws = pow(10, ws * ws * 3.0) - 1.0 + 0.001; //Arctangent
for(i = 0; i < n; i++)
smps[i] = atan(smps[i] * ws) / atan(ws);
break;
case 2:
ws=ws*ws*32.0+0.0001;//Asymmetric
if (ws<1.0) tmpv=sin(ws)+0.1;
else tmpv=1.1;
for (i=0;i<n;i++) {
smps[i]=sin(smps[i]*(0.1+ws-ws*smps[i]))/tmpv;
};
ws = ws * ws * 32.0 + 0.0001; //Asymmetric
if(ws < 1.0)
tmpv = sin(ws) + 0.1;
else
tmpv = 1.1;
for(i = 0; i < n; i++)
smps[i] = sin(smps[i] * (0.1 + ws - ws * smps[i])) / tmpv;
;
break;
case 3:
ws=ws*ws*ws*20.0+0.0001;//Pow
for (i=0;i<n;i++) {
smps[i]*=ws;
if (fabs(smps[i])<1.0) {
smps[i]=(smps[i]-pow(smps[i],3.0))*3.0;
if (ws<1.0) smps[i]/=ws;
} else smps[i]=0.0;
};
ws = ws * ws * ws * 20.0 + 0.0001; //Pow
for(i = 0; i < n; i++) {
smps[i] *= ws;
if(fabs(smps[i]) < 1.0) {
smps[i] = (smps[i] - pow(smps[i], 3.0)) * 3.0;
if(ws < 1.0)
smps[i] /= ws;
}
else
smps[i] = 0.0;
}
break;
case 4:
ws=ws*ws*ws*32.0+0.0001;//Sine
if (ws<1.57) tmpv=sin(ws);
else tmpv=1.0;
for (i=0;i<n;i++) smps[i]=sin(smps[i]*ws)/tmpv;
ws = ws * ws * ws * 32.0 + 0.0001; //Sine
if(ws < 1.57)
tmpv = sin(ws);
else
tmpv = 1.0;
for(i = 0; i < n; i++)
smps[i] = sin(smps[i] * ws) / tmpv;
break;
case 5:
ws=ws*ws+0.000001;//Quantisize
for (i=0;i<n;i++)
smps[i]=floor(smps[i]/ws+0.5)*ws;
ws = ws * ws + 0.000001; //Quantisize
for(i = 0; i < n; i++)
smps[i] = floor(smps[i] / ws + 0.5) * ws;
break;
case 6:
ws=ws*ws*ws*32+0.0001;//Zigzag
if (ws<1.0) tmpv=sin(ws);
else tmpv=1.0;
for (i=0;i<n;i++)
smps[i]=asin(sin(smps[i]*ws))/tmpv;
ws = ws * ws * ws * 32 + 0.0001; //Zigzag
if(ws < 1.0)
tmpv = sin(ws);
else
tmpv = 1.0;
for(i = 0; i < n; i++)
smps[i] = asin(sin(smps[i] * ws)) / tmpv;
break;
case 7:
ws=pow(2.0,-ws*ws*8.0); //Limiter
for (i=0;i<n;i++) {
REALTYPE tmp=smps[i];
if (fabs(tmp)>ws) {
if (tmp>=0.0) smps[i]=1.0;
else smps[i]=-1.0;
} else smps[i]/=ws;
};
ws = pow(2.0, -ws * ws * 8.0); //Limiter
for(i = 0; i < n; i++) {
REALTYPE tmp = smps[i];
if(fabs(tmp) > ws) {
if(tmp >= 0.0)
smps[i] = 1.0;
else
smps[i] = -1.0;
}
else
smps[i] /= ws;
}
break;
case 8:
ws=pow(2.0,-ws*ws*8.0); //Upper Limiter
for (i=0;i<n;i++) {
REALTYPE tmp=smps[i];
if (tmp>ws) smps[i]=ws;
smps[i]*=2.0;
};
ws = pow(2.0, -ws * ws * 8.0); //Upper Limiter
for(i = 0; i < n; i++) {
REALTYPE tmp = smps[i];
if(tmp > ws)
smps[i] = ws;
smps[i] *= 2.0;
}
break;
case 9:
ws=pow(2.0,-ws*ws*8.0); //Lower Limiter
for (i=0;i<n;i++) {
REALTYPE tmp=smps[i];
if (tmp<-ws) smps[i]=-ws;
smps[i]*=2.0;
};
ws = pow(2.0, -ws * ws * 8.0); //Lower Limiter
for(i = 0; i < n; i++) {
REALTYPE tmp = smps[i];
if(tmp < -ws)
smps[i] = -ws;
smps[i] *= 2.0;
}
break;
case 10:
ws=(pow(2.0,ws*6.0)-1.0)/pow(2.0,6.0); //Inverse Limiter
for (i=0;i<n;i++) {
REALTYPE tmp=smps[i];
if (fabs(tmp)>ws) {
if (tmp>=0.0) smps[i]=tmp-ws;
else smps[i]=tmp+ws;
} else smps[i]=0;
};
ws = (pow(2.0, ws * 6.0) - 1.0) / pow(2.0, 6.0); //Inverse Limiter
for(i = 0; i < n; i++) {
REALTYPE tmp = smps[i];
if(fabs(tmp) > ws) {
if(tmp >= 0.0)
smps[i] = tmp - ws;
else
smps[i] = tmp + ws;
}
else
smps[i] = 0;
}
break;
case 11:
ws=pow(5,ws*ws*1.0)-1.0;//Clip
for (i=0;i<n;i++)
smps[i]=smps[i]*(ws+0.5)*0.9999-floor(0.5+smps[i]*(ws+0.5)*0.9999);
ws = pow(5, ws * ws * 1.0) - 1.0; //Clip
for(i = 0; i < n; i++)
smps[i] = smps[i]
* (ws + 0.5) * 0.9999 - floor(
0.5 + smps[i] * (ws + 0.5) * 0.9999);
break;
case 12:
ws=ws*ws*ws*30+0.001;//Asym2
if (ws<0.3) tmpv=ws;
else tmpv=1.0;
for (i=0;i<n;i++) {
REALTYPE tmp=smps[i]*ws;
if ((tmp>-2.0) && (tmp<1.0)) smps[i]=tmp*(1.0-tmp)*(tmp+2.0)/tmpv;
else smps[i]=0.0;
};
ws = ws * ws * ws * 30 + 0.001; //Asym2
if(ws < 0.3)
tmpv = ws;
else
tmpv = 1.0;
for(i = 0; i < n; i++) {
REALTYPE tmp = smps[i] * ws;
if((tmp > -2.0) && (tmp < 1.0))
smps[i] = tmp * (1.0 - tmp) * (tmp + 2.0) / tmpv;
else
smps[i] = 0.0;
}
break;
case 13:
ws=ws*ws*ws*32.0+0.0001;//Pow2
if (ws<1.0) tmpv=ws*(1+ws)/2.0;
else tmpv=1.0;
for (i=0;i<n;i++) {
REALTYPE tmp=smps[i]*ws;
if ((tmp>-1.0)&&(tmp<1.618034)) smps[i]=tmp*(1.0-tmp)/tmpv;
else if (tmp>0.0) smps[i]=-1.0;
else smps[i]=-2.0;
};
ws = ws * ws * ws * 32.0 + 0.0001; //Pow2
if(ws < 1.0)
tmpv = ws * (1 + ws) / 2.0;
else
tmpv = 1.0;
for(i = 0; i < n; i++) {
REALTYPE tmp = smps[i] * ws;
if((tmp > -1.0) && (tmp < 1.618034))
smps[i] = tmp * (1.0 - tmp) / tmpv;
else
if(tmp > 0.0)
smps[i] = -1.0;
else
smps[i] = -2.0;
}
break;
case 14:
ws=pow(ws,5.0)*80.0+0.0001;//sigmoid
if (ws>10.0) tmpv=0.5;
else tmpv=0.5-1.0/(exp(ws)+1.0);
for (i=0;i<n;i++) {
REALTYPE tmp=smps[i]*ws;
if (tmp<-10.0) tmp=-10.0;
else if (tmp>10.0) tmp=10.0;
tmp=0.5-1.0/(exp(tmp)+1.0);
smps[i]=tmp/tmpv;
};
ws = pow(ws, 5.0) * 80.0 + 0.0001; //sigmoid
if(ws > 10.0)
tmpv = 0.5;
else
tmpv = 0.5 - 1.0 / (exp(ws) + 1.0);
for(i = 0; i < n; i++) {
REALTYPE tmp = smps[i] * ws;
if(tmp < -10.0)
tmp = -10.0;
else
if(tmp > 10.0)
tmp = 10.0;
tmp = 0.5 - 1.0 / (exp(tmp) + 1.0);
smps[i] = tmp / tmpv;
}
break;
/**\todo update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions*/
};
};
}
}
Distorsion::Distorsion(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0)
Distorsion::Distorsion(const int &insertion_,
REALTYPE *efxoutl_,
REALTYPE *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0)
{
lpfl=new AnalogFilter(2,22000,1,0);
lpfr=new AnalogFilter(2,22000,1,0);
hpfl=new AnalogFilter(3,20,1,0);
hpfr=new AnalogFilter(3,20,1,0);
lpfl = new AnalogFilter(2, 22000, 1, 0);
lpfr = new AnalogFilter(2, 22000, 1, 0);
hpfl = new AnalogFilter(3, 20, 1, 0);
hpfr = new AnalogFilter(3, 20, 1, 0);
//default values
Pvolume=50;
Plrcross=40;
Pdrive=90;
Plevel=64;
Ptype=0;
Pnegate=0;
Plpf=127;
Phpf=0;
Pstereo=0;
Pprefiltering=0;
Pvolume = 50;
Plrcross = 40;
Pdrive = 90;
Plevel = 64;
Ptype = 0;
Pnegate = 0;
Plpf = 127;
Phpf = 0;
Pstereo = 0;
Pprefiltering = 0;
setpreset(Ppreset);
cleanup();
};
}
Distorsion::~Distorsion()
{
@@ -188,8 +228,7 @@ Distorsion::~Distorsion()
delete lpfr;
delete hpfl;
delete hpfr;
};
}
/*
* Cleanup the effect
@@ -200,72 +239,77 @@ void Distorsion::cleanup()
hpfl->cleanup();
lpfr->cleanup();
hpfr->cleanup();
};
}
/*
* Apply the filters
*/
void Distorsion::applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr)
void Distorsion::applyfilters(REALTYPE *efxoutl, REALTYPE *efxoutr)
{
lpfl->filterout(efxoutl);
hpfl->filterout(efxoutl);
if (Pstereo!=0) {//stereo
if(Pstereo != 0) { //stereo
lpfr->filterout(efxoutr);
hpfr->filterout(efxoutr);
};
};
}
}
/*
* Effect output
*/
void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr)
void Distorsion::out(REALTYPE *smpsl, REALTYPE *smpsr)
{
int i;
REALTYPE l,r,lout,rout;
int i;
REALTYPE l, r, lout, rout;
REALTYPE inputvol=pow(5.0,(Pdrive-32.0)/127.0);
if (Pnegate!=0) inputvol*=-1.0;
REALTYPE inputvol = pow(5.0, (Pdrive - 32.0) / 127.0);
if(Pnegate != 0)
inputvol *= -1.0;
if (Pstereo!=0) {//Stereo
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
efxoutl[i]=smpsl[i]*inputvol*panning;
efxoutr[i]=smpsr[i]*inputvol*(1.0-panning);
};
} else {
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
efxoutl[i]=( smpsl[i]*panning + smpsr[i]*(1.0-panning) ) * inputvol;
};
};
if(Pstereo != 0) { //Stereo
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] = smpsl[i] * inputvol * panning;
efxoutr[i] = smpsr[i] * inputvol * (1.0 - panning);
}
}
else {
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
efxoutl[i] =
(smpsl[i] * panning + smpsr[i] * (1.0 - panning)) * inputvol;
;
}
if (Pprefiltering!=0) applyfilters(efxoutl,efxoutr);
if(Pprefiltering != 0)
applyfilters(efxoutl, efxoutr);
//no optimised, yet (no look table)
waveshapesmps(SOUND_BUFFER_SIZE,efxoutl,Ptype+1,Pdrive);
if (Pstereo!=0) waveshapesmps(SOUND_BUFFER_SIZE,efxoutr,Ptype+1,Pdrive);
waveshapesmps(SOUND_BUFFER_SIZE, efxoutl, Ptype + 1, Pdrive);
if(Pstereo != 0)
waveshapesmps(SOUND_BUFFER_SIZE, efxoutr, Ptype + 1, Pdrive);
if (Pprefiltering==0) applyfilters(efxoutl,efxoutr);
if(Pprefiltering == 0)
applyfilters(efxoutl, efxoutr);
if (Pstereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) efxoutr[i]=efxoutl[i];
if(Pstereo == 0)
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
efxoutr[i] = efxoutl[i];
REALTYPE level=dB2rap(60.0*Plevel/127.0-40.0);
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
lout=efxoutl[i];
rout=efxoutr[i];
l=lout*(1.0-lrcross)+rout*lrcross;
r=rout*(1.0-lrcross)+lout*lrcross;
lout=l;
rout=r;
REALTYPE level = dB2rap(60.0 * Plevel / 127.0 - 40.0);
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
lout = efxoutl[i];
rout = efxoutr[i];
l = lout * (1.0 - lrcross) + rout * lrcross;
r = rout * (1.0 - lrcross) + lout * lrcross;
lout = l;
rout = r;
efxoutl[i]=lout*2.0*level;
efxoutr[i]=rout*2.0*level;
};
};
efxoutl[i] = lout * 2.0 * level;
efxoutr[i] = rout * 2.0 * level;
}
}
/*
@@ -273,79 +317,83 @@ void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr)
*/
void Distorsion::setvolume(const unsigned char &Pvolume)
{
this->Pvolume=Pvolume;
this->Pvolume = Pvolume;
if (insertion==0) {
outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0;
volume=1.0;
} else {
volume=outvolume=Pvolume/127.0;
};
if (Pvolume==0) cleanup();
};
if(insertion == 0) {
outvolume = pow(0.01, (1.0 - Pvolume / 127.0)) * 4.0;
volume = 1.0;
}
else
volume = outvolume = Pvolume / 127.0;
;
if(Pvolume == 0)
cleanup();
}
void Distorsion::setpanning(const unsigned char &Ppanning)
{
this->Ppanning=Ppanning;
panning=(Ppanning+0.5)/127.0;
};
this->Ppanning = Ppanning;
panning = (Ppanning + 0.5) / 127.0;
}
void Distorsion::setlrcross(const unsigned char &Plrcross)
{
this->Plrcross=Plrcross;
lrcross=Plrcross/127.0*1.0;
};
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0 * 1.0;
}
void Distorsion::setlpf(const unsigned char &Plpf)
{
this->Plpf=Plpf;
REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40;
this->Plpf = Plpf;
REALTYPE fr = exp(pow(Plpf / 127.0, 0.5) * log(25000.0)) + 40;
lpfl->setfreq(fr);
lpfr->setfreq(fr);
};
}
void Distorsion::sethpf(const unsigned char &Phpf)
{
this->Phpf=Phpf;
REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(25000.0))+20.0;
this->Phpf = Phpf;
REALTYPE fr = exp(pow(Phpf / 127.0, 0.5) * log(25000.0)) + 20.0;
hpfl->setfreq(fr);
hpfr->setfreq(fr);
};
}
void Distorsion::setpreset(unsigned char npreset)
{
const int PRESET_SIZE=11;
const int NUM_PRESETS=6;
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
const int PRESET_SIZE = 11;
const int NUM_PRESETS = 6;
unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
//Overdrive 1
{127,64,35,56,70,0,0,96,0,0,0},
{127, 64, 35, 56, 70, 0, 0, 96, 0, 0, 0 },
//Overdrive 2
{127,64,35,29,75,1,0,127,0,0,0},
{127, 64, 35, 29, 75, 1, 0, 127, 0, 0, 0 },
//A. Exciter 1
{64,64,35,75,80,5,0,127,105,1,0},
{64, 64, 35, 75, 80, 5, 0, 127, 105, 1, 0 },
//A. Exciter 2
{64,64,35,85,62,1,0,127,118,1,0},
{64, 64, 35, 85, 62, 1, 0, 127, 118, 1, 0 },
//Guitar Amp
{127,64,35,63,75,2,0,55,0,0,0},
{127, 64, 35, 63, 75, 2, 0, 55, 0, 0, 0 },
//Quantisize
{127,64,35,88,75,4,0,127,0,1,0}
{127, 64, 35, 88, 75, 4, 0, 127, 0, 1, 0 }
};
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
if (insertion==0) changepar(0,(int) (presets[npreset][0]/1.5));//lower the volume if this is system effect
Ppreset=npreset;
if(npreset >= NUM_PRESETS)
npreset = NUM_PRESETS - 1;
for(int n = 0; n < PRESET_SIZE; n++)
changepar(n, presets[npreset][n]);
if(insertion == 0)
changepar(0, (int) (presets[npreset][0] / 1.5)); //lower the volume if this is system effect
Ppreset = npreset;
cleanup();
};
}
void Distorsion::changepar(const int &npar,const unsigned char &value)
void Distorsion::changepar(const int &npar, const unsigned char &value)
{
switch (npar) {
switch(npar) {
case 0:
setvolume(value);
break;
@@ -356,18 +404,22 @@ void Distorsion::changepar(const int &npar,const unsigned char &value)
setlrcross(value);
break;
case 3:
Pdrive=value;
Pdrive = value;
break;
case 4:
Plevel=value;
Plevel = value;
break;
case 5:
if (value>13) Ptype=13;//this must be increased if more distorsion types are added
else Ptype=value;
if(value > 13)
Ptype = 13; //this must be increased if more distorsion types are added
else
Ptype = value;
break;
case 6:
if (value>1) Pnegate=1;
else Pnegate=value;
if(value > 1)
Pnegate = 1;
else
Pnegate = value;
break;
case 7:
setlpf(value);
@@ -376,52 +428,54 @@ void Distorsion::changepar(const int &npar,const unsigned char &value)
sethpf(value);
break;
case 9:
if (value>1) Pstereo=1;
else Pstereo=value;
if(value > 1)
Pstereo = 1;
else
Pstereo = value;
break;
case 10:
Pprefiltering=value;
Pprefiltering = value;
break;
};
};
}
}
unsigned char Distorsion::getpar(const int &npar)const
unsigned char Distorsion::getpar(const int &npar) const
{
switch (npar) {
switch(npar) {
case 0:
return(Pvolume);
return Pvolume;
break;
case 1:
return(Ppanning);
return Ppanning;
break;
case 2:
return(Plrcross);
return Plrcross;
break;
case 3:
return(Pdrive);
return Pdrive;
break;
case 4:
return(Plevel);
return Plevel;
break;
case 5:
return(Ptype);
return Ptype;
break;
case 6:
return(Pnegate);
return Pnegate;
break;
case 7:
return(Plpf);
return Plpf;
break;
case 8:
return(Phpf);
return Phpf;
break;
case 9:
return(Pstereo);
return Pstereo;
break;
case 10:
return(Pprefiltering);
return Pprefiltering;
break;
};
return(0);//in case of bogus parameter number
};
}
return 0; //in case of bogus parameter number
}

View File

@@ -28,44 +28,46 @@
#include "Effect.h"
//Waveshaping(called by Distorsion effect and waveshape from OscilGen)
void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive);
void waveshapesmps(int n,
REALTYPE *smps,
unsigned char type,
unsigned char drive);
/**Distortion Effect*/
class Distorsion:public Effect
{
public:
Distorsion(const int &insertion,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
~Distorsion();
void out(REALTYPE *smpsl,REALTYPE *smpr);
void setpreset(unsigned char npreset);
void changepar(const int &npar,const unsigned char &value);
unsigned char getpar(const int &npar)const;
void cleanup();
void applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr);
public:
Distorsion(const int &insertion, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~Distorsion();
void out(REALTYPE *smpsl, REALTYPE *smpr);
void setpreset(unsigned char npreset);
void changepar(const int &npar, const unsigned char &value);
unsigned char getpar(const int &npar) const;
void cleanup();
void applyfilters(REALTYPE *efxoutl, REALTYPE *efxoutr);
private:
//Parametrii
unsigned char Pvolume; //Volumul or E/R
unsigned char Ppanning;//Panning
unsigned char Plrcross;// L/R Mixing
unsigned char Pdrive; //the input amplification
unsigned char Plevel; //the output amplification
unsigned char Ptype; //Distorsion type
unsigned char Pnegate; //if the input is negated
unsigned char Plpf; //lowpass filter
unsigned char Phpf; //highpass filter
unsigned char Pstereo; //0=mono,1=stereo
unsigned char Pprefiltering;//if you want to do the filtering before the distorsion
private:
//Parametrii
unsigned char Pvolume; //Volumul or E/R
unsigned char Ppanning; //Panning
unsigned char Plrcross; // L/R Mixing
unsigned char Pdrive; //the input amplification
unsigned char Plevel; //the output amplification
unsigned char Ptype; //Distorsion type
unsigned char Pnegate; //if the input is negated
unsigned char Plpf; //lowpass filter
unsigned char Phpf; //highpass filter
unsigned char Pstereo; //0=mono,1=stereo
unsigned char Pprefiltering; //if you want to do the filtering before the distorsion
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setlrcross(const unsigned char &Plrcross);
void setlpf(const unsigned char &Plpf);
void sethpf(const unsigned char &Phpf);
//Real Parameters
REALTYPE panning,lrcross;
AnalogFilter *lpfl,*lpfr,*hpfl,*hpfr;
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setlrcross(const unsigned char &Plrcross);
void setlpf(const unsigned char &Plpf);
void sethpf(const unsigned char &Phpf);
//Real Parameters
REALTYPE panning, lrcross;
AnalogFilter *lpfl, *lpfr, *hpfl, *hpfr;
};

View File

@@ -23,74 +23,75 @@
#include <cmath>
#include "DynamicFilter.h"
DynamicFilter::DynamicFilter(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
:Effect(insertion_,efxoutl_,efxoutr_,new FilterParams(0,64,64),0),
Pvolume(110),Ppanning(64),Pdepth(0),Pampsns(90),
Pampsnsinv(0),Pampsmooth(60),
filterl(NULL),filterr(NULL)
DynamicFilter::DynamicFilter(int insertion_,
REALTYPE *efxoutl_,
REALTYPE *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, new FilterParams(0, 64, 64), 0),
Pvolume(110), Ppanning(64), Pdepth(0), Pampsns(90),
Pampsnsinv(0), Pampsmooth(60),
filterl(NULL), filterr(NULL)
{
setpreset(Ppreset);
cleanup();
};
}
DynamicFilter::~DynamicFilter()
{
delete filterpars;
delete filterl;
delete filterr;
};
}
/*
* Apply the effect
*/
void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr)
void DynamicFilter::out(REALTYPE *smpsl, REALTYPE *smpsr)
{
int i;
if (filterpars->changed) {
filterpars->changed=false;
if(filterpars->changed) {
filterpars->changed = false;
cleanup();
};
}
REALTYPE lfol,lfor;
lfo.effectlfoout(&lfol,&lfor);
lfol*=depth*5.0;
lfor*=depth*5.0;
REALTYPE freq=filterpars->getfreq();
REALTYPE q=filterpars->getq();
REALTYPE lfol, lfor;
lfo.effectlfoout(&lfol, &lfor);
lfol *= depth * 5.0;
lfor *= depth * 5.0;
REALTYPE freq = filterpars->getfreq();
REALTYPE q = filterpars->getq();
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
efxoutl[i]=smpsl[i];
efxoutr[i]=smpsr[i];
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] = smpsl[i];
efxoutr[i] = smpsr[i];
REALTYPE x=(fabs(smpsl[i])+fabs(smpsr[i]))*0.5;
ms1=ms1*(1.0-ampsmooth)+x*ampsmooth+1e-10;
};
REALTYPE x = (fabs(smpsl[i]) + fabs(smpsr[i])) * 0.5;
ms1 = ms1 * (1.0 - ampsmooth) + x * ampsmooth + 1e-10;
}
REALTYPE ampsmooth2=pow(ampsmooth,0.2)*0.3;
ms2=ms2*(1.0-ampsmooth2)+ms1*ampsmooth2;
ms3=ms3*(1.0-ampsmooth2)+ms2*ampsmooth2;
ms4=ms4*(1.0-ampsmooth2)+ms3*ampsmooth2;
REALTYPE rms=(sqrt(ms4))*ampsns;
REALTYPE ampsmooth2 = pow(ampsmooth, 0.2) * 0.3;
ms2 = ms2 * (1.0 - ampsmooth2) + ms1 * ampsmooth2;
ms3 = ms3 * (1.0 - ampsmooth2) + ms2 * ampsmooth2;
ms4 = ms4 * (1.0 - ampsmooth2) + ms3 * ampsmooth2;
REALTYPE rms = (sqrt(ms4)) * ampsns;
REALTYPE frl=filterl->getrealfreq(freq+lfol+rms);
REALTYPE frr=filterr->getrealfreq(freq+lfor+rms);
REALTYPE frl = filterl->getrealfreq(freq + lfol + rms);
REALTYPE frr = filterr->getrealfreq(freq + lfor + rms);
filterl->setfreq_and_q(frl,q);
filterr->setfreq_and_q(frr,q);
filterl->setfreq_and_q(frl, q);
filterr->setfreq_and_q(frr, q);
filterl->filterout(efxoutl);
filterr->filterout(efxoutr);
//panning
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
efxoutl[i]*=panning;
efxoutr[i]*=(1.0-panning);
};
};
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] *= panning;
efxoutr[i] *= (1.0 - panning);
}
}
/*
* Cleanup the effect
@@ -98,11 +99,11 @@ void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr)
void DynamicFilter::cleanup()
{
reinitfilter();
ms1=0.0;
ms2=0.0;
ms3=0.0;
ms4=0.0;
};
ms1 = 0.0;
ms2 = 0.0;
ms3 = 0.0;
ms4 = 0.0;
}
/*
@@ -111,159 +112,167 @@ void DynamicFilter::cleanup()
void DynamicFilter::setdepth(const unsigned char &Pdepth)
{
this->Pdepth=Pdepth;
depth=pow((Pdepth/127.0),2.0);
};
this->Pdepth = Pdepth;
depth = pow((Pdepth / 127.0), 2.0);
}
void DynamicFilter::setvolume(const unsigned char &Pvolume)
{
this->Pvolume=Pvolume;
outvolume=Pvolume/127.0;
if (insertion==0) volume=1.0;
else volume=outvolume;
};
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
if(insertion == 0)
volume = 1.0;
else
volume = outvolume;
}
void DynamicFilter::setpanning(const unsigned char &Ppanning)
{
this->Ppanning=Ppanning;
panning=Ppanning/127.0;
};
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
void DynamicFilter::setampsns(const unsigned char &Pampsns)
{
ampsns=pow(Pampsns/127.0,2.5)*10.0;
if (Pampsnsinv!=0) ampsns=-ampsns;
ampsmooth=exp(-Pampsmooth/127.0*10.0)*0.99;
this->Pampsns=Pampsns;
};
ampsns = pow(Pampsns / 127.0, 2.5) * 10.0;
if(Pampsnsinv != 0)
ampsns = -ampsns;
ampsmooth = exp(-Pampsmooth / 127.0 * 10.0) * 0.99;
this->Pampsns = Pampsns;
}
void DynamicFilter::reinitfilter()
{
if (filterl!=NULL) delete(filterl);
if (filterr!=NULL) delete(filterr);
filterl=new Filter(filterpars);
filterr=new Filter(filterpars);
};
if(filterl != NULL)
delete (filterl);
if(filterr != NULL)
delete (filterr);
filterl = new Filter(filterpars);
filterr = new Filter(filterpars);
}
void DynamicFilter::setpreset(unsigned char npreset)
{
const int PRESET_SIZE=10;
const int NUM_PRESETS=5;
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
const int PRESET_SIZE = 10;
const int NUM_PRESETS = 5;
unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
//WahWah
{110,64,80,0,0,64,0,90,0,60},
{110, 64, 80, 0, 0, 64, 0, 90, 0, 60},
//AutoWah
{110,64,70,0,0,80,70,0,0,60},
{110, 64, 70, 0, 0, 80, 70, 0, 0, 60},
//Sweep
{100,64,30,0,0,50,80,0,0,60},
{100, 64, 30, 0, 0, 50, 80, 0, 0, 60},
//VocalMorph1
{110,64,80,0,0,64,0,64,0,60},
{110, 64, 80, 0, 0, 64, 0, 64, 0, 60},
//VocalMorph1
{127,64,50,0,0,96,64,0,0,60}
{127, 64, 50, 0, 0, 96, 64, 0, 0, 60}
};
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
if(npreset >= NUM_PRESETS)
npreset = NUM_PRESETS - 1;
for(int n = 0; n < PRESET_SIZE; n++)
changepar(n, presets[npreset][n]);
filterpars->defaults();
switch (npreset) {
switch(npreset) {
case 0:
filterpars->Pcategory=0;
filterpars->Ptype=2;
filterpars->Pfreq=45;
filterpars->Pq=64;
filterpars->Pstages=1;
filterpars->Pgain=64;
filterpars->Pcategory = 0;
filterpars->Ptype = 2;
filterpars->Pfreq = 45;
filterpars->Pq = 64;
filterpars->Pstages = 1;
filterpars->Pgain = 64;
break;
case 1:
filterpars->Pcategory=2;
filterpars->Ptype=0;
filterpars->Pfreq=72;
filterpars->Pq=64;
filterpars->Pstages=0;
filterpars->Pgain=64;
filterpars->Pcategory = 2;
filterpars->Ptype = 0;
filterpars->Pfreq = 72;
filterpars->Pq = 64;
filterpars->Pstages = 0;
filterpars->Pgain = 64;
break;
case 2:
filterpars->Pcategory=0;
filterpars->Ptype=4;
filterpars->Pfreq=64;
filterpars->Pq=64;
filterpars->Pstages=2;
filterpars->Pgain=64;
filterpars->Pcategory = 0;
filterpars->Ptype = 4;
filterpars->Pfreq = 64;
filterpars->Pq = 64;
filterpars->Pstages = 2;
filterpars->Pgain = 64;
break;
case 3:
filterpars->Pcategory=1;
filterpars->Ptype=0;
filterpars->Pfreq=50;
filterpars->Pq=70;
filterpars->Pstages=1;
filterpars->Pgain=64;
filterpars->Pcategory = 1;
filterpars->Ptype = 0;
filterpars->Pfreq = 50;
filterpars->Pq = 70;
filterpars->Pstages = 1;
filterpars->Pgain = 64;
filterpars->Psequencesize=2;
filterpars->Psequencesize = 2;
// "I"
filterpars->Pvowels[0].formants[0].freq=34;
filterpars->Pvowels[0].formants[0].amp=127;
filterpars->Pvowels[0].formants[0].q=64;
filterpars->Pvowels[0].formants[1].freq=99;
filterpars->Pvowels[0].formants[1].amp=122;
filterpars->Pvowels[0].formants[1].q=64;
filterpars->Pvowels[0].formants[2].freq=108;
filterpars->Pvowels[0].formants[2].amp=112;
filterpars->Pvowels[0].formants[2].q=64;
filterpars->Pvowels[0].formants[0].freq = 34;
filterpars->Pvowels[0].formants[0].amp = 127;
filterpars->Pvowels[0].formants[0].q = 64;
filterpars->Pvowels[0].formants[1].freq = 99;
filterpars->Pvowels[0].formants[1].amp = 122;
filterpars->Pvowels[0].formants[1].q = 64;
filterpars->Pvowels[0].formants[2].freq = 108;
filterpars->Pvowels[0].formants[2].amp = 112;
filterpars->Pvowels[0].formants[2].q = 64;
// "A"
filterpars->Pvowels[1].formants[0].freq=61;
filterpars->Pvowels[1].formants[0].amp=127;
filterpars->Pvowels[1].formants[0].q=64;
filterpars->Pvowels[1].formants[1].freq=71;
filterpars->Pvowels[1].formants[1].amp=121;
filterpars->Pvowels[1].formants[1].q=64;
filterpars->Pvowels[1].formants[2].freq=99;
filterpars->Pvowels[1].formants[2].amp=117;
filterpars->Pvowels[1].formants[2].q=64;
filterpars->Pvowels[1].formants[0].freq = 61;
filterpars->Pvowels[1].formants[0].amp = 127;
filterpars->Pvowels[1].formants[0].q = 64;
filterpars->Pvowels[1].formants[1].freq = 71;
filterpars->Pvowels[1].formants[1].amp = 121;
filterpars->Pvowels[1].formants[1].q = 64;
filterpars->Pvowels[1].formants[2].freq = 99;
filterpars->Pvowels[1].formants[2].amp = 117;
filterpars->Pvowels[1].formants[2].q = 64;
break;
case 4:
filterpars->Pcategory=1;
filterpars->Ptype=0;
filterpars->Pfreq=64;
filterpars->Pq=70;
filterpars->Pstages=1;
filterpars->Pgain=64;
filterpars->Pcategory = 1;
filterpars->Ptype = 0;
filterpars->Pfreq = 64;
filterpars->Pq = 70;
filterpars->Pstages = 1;
filterpars->Pgain = 64;
filterpars->Psequencesize=2;
filterpars->Pnumformants=2;
filterpars->Pvowelclearness=0;
filterpars->Psequencesize = 2;
filterpars->Pnumformants = 2;
filterpars->Pvowelclearness = 0;
filterpars->Pvowels[0].formants[0].freq=70;
filterpars->Pvowels[0].formants[0].amp=127;
filterpars->Pvowels[0].formants[0].q=64;
filterpars->Pvowels[0].formants[1].freq=80;
filterpars->Pvowels[0].formants[1].amp=122;
filterpars->Pvowels[0].formants[1].q=64;
filterpars->Pvowels[0].formants[0].freq = 70;
filterpars->Pvowels[0].formants[0].amp = 127;
filterpars->Pvowels[0].formants[0].q = 64;
filterpars->Pvowels[0].formants[1].freq = 80;
filterpars->Pvowels[0].formants[1].amp = 122;
filterpars->Pvowels[0].formants[1].q = 64;
filterpars->Pvowels[1].formants[0].freq=20;
filterpars->Pvowels[1].formants[0].amp=127;
filterpars->Pvowels[1].formants[0].q=64;
filterpars->Pvowels[1].formants[1].freq=100;
filterpars->Pvowels[1].formants[1].amp=121;
filterpars->Pvowels[1].formants[1].q=64;
filterpars->Pvowels[1].formants[0].freq = 20;
filterpars->Pvowels[1].formants[0].amp = 127;
filterpars->Pvowels[1].formants[0].q = 64;
filterpars->Pvowels[1].formants[1].freq = 100;
filterpars->Pvowels[1].formants[1].amp = 121;
filterpars->Pvowels[1].formants[1].q = 64;
break;
};
}
// for (int i=0;i<5;i++){
// printf("freq=%d amp=%d q=%d\n",filterpars->Pvowels[0].formants[i].freq,filterpars->Pvowels[0].formants[i].amp,filterpars->Pvowels[0].formants[i].q);
// };
if (insertion==0) changepar(0,presets[npreset][0]/2);//lower the volume if this is system effect
Ppreset=npreset;
if(insertion == 0)
changepar(0, presets[npreset][0] / 2); //lower the volume if this is system effect
Ppreset = npreset;
reinitfilter();
};
}
void DynamicFilter::changepar(const int &npar,const unsigned char &value)
void DynamicFilter::changepar(const int &npar, const unsigned char &value)
{
switch (npar) {
switch(npar) {
case 0:
setvolume(value);
break;
@@ -271,19 +280,19 @@ void DynamicFilter::changepar(const int &npar,const unsigned char &value)
setpanning(value);
break;
case 2:
lfo.Pfreq=value;
lfo.Pfreq = value;
lfo.updateparams();
break;
case 3:
lfo.Prandomness=value;
lfo.Prandomness = value;
lfo.updateparams();
break;
case 4:
lfo.PLFOtype=value;
lfo.PLFOtype = value;
lfo.updateparams();
break;
case 5:
lfo.Pstereo=value;
lfo.Pstereo = value;
lfo.updateparams();
break;
case 6:
@@ -293,52 +302,51 @@ void DynamicFilter::changepar(const int &npar,const unsigned char &value)
setampsns(value);
break;
case 8:
Pampsnsinv=value;
Pampsnsinv = value;
setampsns(Pampsns);
break;
case 9:
Pampsmooth=value;
Pampsmooth = value;
setampsns(Pampsns);
break;
};
};
}
}
unsigned char DynamicFilter::getpar(const int &npar)const
unsigned char DynamicFilter::getpar(const int &npar) const
{
switch (npar) {
switch(npar) {
case 0:
return(Pvolume);
return Pvolume;
break;
case 1:
return(Ppanning);
return Ppanning;
break;
case 2:
return(lfo.Pfreq);
return lfo.Pfreq;
break;
case 3:
return(lfo.Prandomness);
return lfo.Prandomness;
break;
case 4:
return(lfo.PLFOtype);
return lfo.PLFOtype;
break;
case 5:
return(lfo.Pstereo);
return lfo.Pstereo;
break;
case 6:
return(Pdepth);
return Pdepth;
break;
case 7:
return(Pampsns);
return Pampsns;
break;
case 8:
return(Pampsnsinv);
return Pampsnsinv;
break;
case 9:
return(Pampsmooth);
return Pampsmooth;
break;
default:
return (0);
};
};
return 0;
}
}

View File

@@ -30,42 +30,42 @@
/**DynamicFilter Effect*/
class DynamicFilter:public Effect
{
public:
DynamicFilter(int insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
~DynamicFilter();
void out(REALTYPE *smpsl,REALTYPE *smpsr);
public:
DynamicFilter(int insetion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~DynamicFilter();
void out(REALTYPE *smpsl, REALTYPE *smpsr);
void setpreset(unsigned char npreset);
void changepar(const int &npar,const unsigned char &value);
unsigned char getpar(const int &npar)const;
void cleanup();
void setpreset(unsigned char npreset);
void changepar(const int &npar, const unsigned char &value);
unsigned char getpar(const int &npar) const;
void cleanup();
// void setdryonly();
private:
//Parametrii DynamicFilter
EffectLFO lfo;//lfo-ul DynamicFilter
unsigned char Pvolume;
unsigned char Ppanning;
unsigned char Pdepth;/**<the depth of the lfo of the DynamicFilter*/
unsigned char Pampsns;/**<how the filter varies according to the input amplitude*/
unsigned char Pampsnsinv;//if the filter freq is lowered if the input amplitude rises
unsigned char Pampsmooth;//how smooth the input amplitude changes the filter
private:
//Parametrii DynamicFilter
EffectLFO lfo; //lfo-ul DynamicFilter
unsigned char Pvolume;
unsigned char Ppanning;
unsigned char Pdepth; /**<the depth of the lfo of the DynamicFilter*/
unsigned char Pampsns; /**<how the filter varies according to the input amplitude*/
unsigned char Pampsnsinv; //if the filter freq is lowered if the input amplitude rises
unsigned char Pampsmooth; //how smooth the input amplitude changes the filter
//Parameter Control
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setdepth(const unsigned char &Pdepth);
void setampsns(const unsigned char &Pampsns);
//Parameter Control
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setdepth(const unsigned char &Pdepth);
void setampsns(const unsigned char &Pampsns);
void reinitfilter();
void reinitfilter();
//Internal Values
REALTYPE panning,depth,ampsns,ampsmooth;
//Internal Values
REALTYPE panning, depth, ampsns, ampsmooth;
Filter *filterl,*filterr;
Filter *filterl, *filterr;
REALTYPE ms1,ms2,ms3,ms4;//mean squares
REALTYPE ms1, ms2, ms3, ms4; //mean squares
};
#endif

View File

@@ -23,60 +23,59 @@
#include <cmath>
#include "EQ.h"
EQ::EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0)
EQ::EQ(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0)
{
for (int i=0;i<MAX_EQ_BANDS;i++) {
filter[i].Ptype=0;
filter[i].Pfreq=64;
filter[i].Pgain=64;
filter[i].Pq=64;
filter[i].Pstages=0;
filter[i].l=new AnalogFilter(6,1000.0,1.0,0);
filter[i].r=new AnalogFilter(6,1000.0,1.0,0);
};
for(int i = 0; i < MAX_EQ_BANDS; i++) {
filter[i].Ptype = 0;
filter[i].Pfreq = 64;
filter[i].Pgain = 64;
filter[i].Pq = 64;
filter[i].Pstages = 0;
filter[i].l = new AnalogFilter(6, 1000.0, 1.0, 0);
filter[i].r = new AnalogFilter(6, 1000.0, 1.0, 0);
}
//default values
Pvolume=50;
Pvolume = 50;
setpreset(Ppreset);
cleanup();
};
}
EQ::~EQ()
{
};
{}
/*
* Cleanup the effect
*/
void EQ::cleanup()
{
for (int i=0;i<MAX_EQ_BANDS;i++) {
for(int i = 0; i < MAX_EQ_BANDS; i++) {
filter[i].l->cleanup();
filter[i].r->cleanup();
};
};
}
}
/*
* Effect output
*/
void EQ::out(REALTYPE *smpsl,REALTYPE *smpsr)
void EQ::out(REALTYPE *smpsl, REALTYPE *smpsr)
{
int i;
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
efxoutl[i]=smpsl[i]*volume;
efxoutr[i]=smpsr[i]*volume;
};
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] = smpsl[i] * volume;
efxoutr[i] = smpsr[i] * volume;
}
for (i=0;i<MAX_EQ_BANDS;i++) {
if (filter[i].Ptype==0) continue;
for(i = 0; i < MAX_EQ_BANDS; i++) {
if(filter[i].Ptype == 0)
continue;
filter[i].l->filterout(efxoutl);
filter[i].r->filterout(efxoutr);
};
};
}
}
/*
@@ -84,131 +83,138 @@ void EQ::out(REALTYPE *smpsl,REALTYPE *smpsr)
*/
void EQ::setvolume(const unsigned char &Pvolume)
{
this->Pvolume=Pvolume;
this->Pvolume = Pvolume;
outvolume=pow(0.005,(1.0-Pvolume/127.0))*10.0;
if (insertion==0) {
volume=1.0;
} else {
volume=outvolume;
};
};
outvolume = pow(0.005, (1.0 - Pvolume / 127.0)) * 10.0;
if(insertion == 0)
volume = 1.0;
else
volume = outvolume;
;
}
void EQ::setpreset(unsigned char npreset)
{
const int PRESET_SIZE=1;
const int NUM_PRESETS=2;
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
const int PRESET_SIZE = 1;
const int NUM_PRESETS = 2;
unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
//EQ 1
{67},
//EQ 2
{67}
};
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
Ppreset=npreset;
};
if(npreset >= NUM_PRESETS)
npreset = NUM_PRESETS - 1;
for(int n = 0; n < PRESET_SIZE; n++)
changepar(n, presets[npreset][n]);
Ppreset = npreset;
}
void EQ::changepar(const int &npar,const unsigned char &value)
void EQ::changepar(const int &npar, const unsigned char &value)
{
switch (npar) {
switch(npar) {
case 0:
setvolume(value);
break;
};
if (npar<10) return;
}
if(npar < 10)
return;
int nb=(npar-10)/5;//number of the band (filter)
if (nb>=MAX_EQ_BANDS) return;
int bp=npar%5;//band paramenter
int nb = (npar - 10) / 5; //number of the band (filter)
if(nb >= MAX_EQ_BANDS)
return;
int bp = npar % 5; //band paramenter
REALTYPE tmp;
switch (bp) {
switch(bp) {
case 0:
filter[nb].Ptype=value;
if (value>9) filter[nb].Ptype=0;//has to be changed if more filters will be added
if (filter[nb].Ptype!=0) {
filter[nb].l->settype(value-1);
filter[nb].r->settype(value-1);
};
filter[nb].Ptype = value;
if(value > 9)
filter[nb].Ptype = 0; //has to be changed if more filters will be added
if(filter[nb].Ptype != 0) {
filter[nb].l->settype(value - 1);
filter[nb].r->settype(value - 1);
}
break;
case 1:
filter[nb].Pfreq=value;
tmp=600.0*pow(30.0,(value-64.0)/64.0);
filter[nb].Pfreq = value;
tmp = 600.0 * pow(30.0, (value - 64.0) / 64.0);
filter[nb].l->setfreq(tmp);
filter[nb].r->setfreq(tmp);
break;
case 2:
filter[nb].Pgain=value;
tmp=30.0*(value-64.0)/64.0;
filter[nb].Pgain = value;
tmp = 30.0 * (value - 64.0) / 64.0;
filter[nb].l->setgain(tmp);
filter[nb].r->setgain(tmp);
break;
case 3:
filter[nb].Pq=value;
tmp=pow(30.0,(value-64.0)/64.0);
filter[nb].Pq = value;
tmp = pow(30.0, (value - 64.0) / 64.0);
filter[nb].l->setq(tmp);
filter[nb].r->setq(tmp);
break;
case 4:
filter[nb].Pstages=value;
if (value>=MAX_FILTER_STAGES) filter[nb].Pstages=MAX_FILTER_STAGES-1;
filter[nb].Pstages = value;
if(value >= MAX_FILTER_STAGES)
filter[nb].Pstages = MAX_FILTER_STAGES - 1;
filter[nb].l->setstages(value);
filter[nb].r->setstages(value);
break;
};
};
}
}
unsigned char EQ::getpar(const int &npar)const
unsigned char EQ::getpar(const int &npar) const
{
switch (npar) {
switch(npar) {
case 0:
return(Pvolume);
return Pvolume;
break;
};
}
if (npar<10) return(0);
if(npar < 10)
return 0;
int nb=(npar-10)/5;//number of the band (filter)
if (nb>=MAX_EQ_BANDS) return(0);
int bp=npar%5;//band paramenter
switch (bp) {
int nb = (npar - 10) / 5; //number of the band (filter)
if(nb >= MAX_EQ_BANDS)
return 0;
int bp = npar % 5; //band paramenter
switch(bp) {
case 0:
return(filter[nb].Ptype);
return filter[nb].Ptype;
break;
case 1:
return(filter[nb].Pfreq);
return filter[nb].Pfreq;
break;
case 2:
return(filter[nb].Pgain);
return filter[nb].Pgain;
break;
case 3:
return(filter[nb].Pq);
return filter[nb].Pq;
break;
case 4:
return(filter[nb].Pstages);
return filter[nb].Pstages;
break;
};
}
return(0);//in case of bogus parameter number
};
return 0; //in case of bogus parameter number
}
REALTYPE EQ::getfreqresponse(REALTYPE freq)
{
REALTYPE resp=1.0;
for (int i=0;i<MAX_EQ_BANDS;i++) {
if (filter[i].Ptype==0) continue;
resp*=filter[i].l->H(freq);
};
return(rap2dB(resp*outvolume));
};
REALTYPE resp = 1.0;
for(int i = 0; i < MAX_EQ_BANDS; i++) {
if(filter[i].Ptype == 0)
continue;
resp *= filter[i].l->H(freq);
}
return rap2dB(resp * outvolume);
}

View File

@@ -30,31 +30,29 @@
/**EQ Effect*/
class EQ:public Effect
{
public:
EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
~EQ();
void out(REALTYPE *smpsl,REALTYPE *smpr);
void setpreset(unsigned char npreset);
void changepar(const int &npar,const unsigned char &value);
unsigned char getpar(const int &npar)const;
void cleanup();
REALTYPE getfreqresponse(REALTYPE freq);
private:
//Parameters
unsigned char Pvolume;/**<Volume*/
public:
EQ(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~EQ();
void out(REALTYPE *smpsl, REALTYPE *smpr);
void setpreset(unsigned char npreset);
void changepar(const int &npar, const unsigned char &value);
unsigned char getpar(const int &npar) const;
void cleanup();
REALTYPE getfreqresponse(REALTYPE freq);
private:
//Parameters
unsigned char Pvolume; /**<Volume*/
void setvolume(const unsigned char &Pvolume);
struct {
//parameters
unsigned char Ptype,Pfreq,Pgain,Pq,Pstages;
//internal values
AnalogFilter *l,*r;
}filter[MAX_EQ_BANDS];
void setvolume(const unsigned char &Pvolume);
struct {
//parameters
unsigned char Ptype, Pfreq, Pgain, Pq, Pstages;
//internal values
AnalogFilter *l, *r;
} filter[MAX_EQ_BANDS];
};
#endif

View File

@@ -24,11 +24,13 @@
#include <iostream>
#include "Echo.h"
Echo::Echo(const int & insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_)
: Effect(insertion_,efxoutl_,efxoutr_,NULL,0),
Pvolume(50),Ppanning(64),//Pdelay(60),
Plrdelay(100),Plrcross(100),Pfb(40),Phidamp(60),
lrdelay(0),delaySample(1),old(0.0)
Echo::Echo(const int &insertion_,
REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
Pvolume(50), Ppanning(64), //Pdelay(60),
Plrdelay(100), Plrcross(100), Pfb(40), Phidamp(60),
lrdelay(0), delaySample(1), old(0.0)
{
setpreset(Ppreset);
}
@@ -42,7 +44,7 @@ void Echo::cleanup()
{
delaySample.l().clear();
delaySample.r().clear();
old=Stereo<REALTYPE>(0.0);
old = Stereo<REALTYPE>(0.0);
}
@@ -52,85 +54,91 @@ void Echo::cleanup()
void Echo::initdelays()
{
/**\todo make this adjust insted of destroy old delays*/
kl=0;
kr=0;
dl=(int)(1+delay.getiVal()*SAMPLE_RATE-lrdelay);
if (dl<1) dl=1;
dr=(int)(1+delay.getiVal()*SAMPLE_RATE+lrdelay);
if (dr<1) dr=1;
kl = 0;
kr = 0;
dl = (int)(1 + delay.getiVal() * SAMPLE_RATE - lrdelay);
if(dl < 1)
dl = 1;
dr = (int)(1 + delay.getiVal() * SAMPLE_RATE + lrdelay);
if(dr < 1)
dr = 1;
delaySample.l()=AuSample(dl);
delaySample.r()=AuSample(dr);
delaySample.l() = AuSample(dl);
delaySample.r() = AuSample(dr);
old=Stereo<REALTYPE>(0.0);
old = Stereo<REALTYPE>(0.0);
}
/*
* Effect output
*/
void Echo::out(REALTYPE *const smpsl,REALTYPE *const smpsr)
void Echo::out(REALTYPE *const smpsl, REALTYPE *const smpsr)
{
Stereo<AuSample> input(AuSample(SOUND_BUFFER_SIZE,smpsl),AuSample(SOUND_BUFFER_SIZE,smpsr));
Stereo<AuSample> input(AuSample(SOUND_BUFFER_SIZE, smpsl), AuSample(
SOUND_BUFFER_SIZE,
smpsr));
out(input);
}
void Echo::out(const Stereo<AuSample> &input)
{
//void Echo::out(const Stereo<AuSample> & input){ //ideal
REALTYPE l,r,ldl,rdl;/**\todo move l+r->? ldl+rdl->?*/
REALTYPE l, r, ldl, rdl; /**\todo move l+r->? ldl+rdl->?*/
for (int i=0;i<input.l().size();i++) {
ldl=delaySample.l()[kl];
rdl=delaySample.r()[kr];
l=ldl*(1.0-lrcross)+rdl*lrcross;
r=rdl*(1.0-lrcross)+ldl*lrcross;
ldl=l;
rdl=r;
for(int i = 0; i < input.l().size(); i++) {
ldl = delaySample.l()[kl];
rdl = delaySample.r()[kr];
l = ldl * (1.0 - lrcross) + rdl * lrcross;
r = rdl * (1.0 - lrcross) + ldl * lrcross;
ldl = l;
rdl = r;
efxoutl[i]=ldl*2.0;
efxoutr[i]=rdl*2.0;
efxoutl[i] = ldl * 2.0;
efxoutr[i] = rdl * 2.0;
ldl=input.l()[i]*panning-ldl*fb;
rdl=input.r()[i]*(1.0-panning)-rdl*fb;
ldl = input.l()[i] * panning - ldl * fb;
rdl = input.r()[i] * (1.0 - panning) - rdl * fb;
//LowPass Filter
delaySample.l()[kl]=ldl=ldl*hidamp+old.l()*(1.0-hidamp);
delaySample.r()[kr]=rdl=rdl*hidamp+old.r()*(1.0-hidamp);
old.l()=ldl;
old.r()=rdl;
if (++kl>=dl) kl=0;
if (++kr>=dr) kr=0;
};
delaySample.l()[kl] = ldl = ldl * hidamp + old.l() * (1.0 - hidamp);
delaySample.r()[kr] = rdl = rdl * hidamp + old.r() * (1.0 - hidamp);
old.l() = ldl;
old.r() = rdl;
if(++kl >= dl)
kl = 0;
if(++kr >= dr)
kr = 0;
}
}
/*
* Parameter control
*/
void Echo::setvolume(const unsigned char & Pvolume)
void Echo::setvolume(const unsigned char &Pvolume)
{
this->Pvolume=Pvolume;
if (insertion==0) {
outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0;
volume=1.0;
} else {
volume=outvolume=Pvolume/127.0;
};
if (Pvolume==0) cleanup();
this->Pvolume = Pvolume;
if(insertion == 0) {
outvolume = pow(0.01, (1.0 - Pvolume / 127.0)) * 4.0;
volume = 1.0;
}
else
volume = outvolume = Pvolume / 127.0;
;
if(Pvolume == 0)
cleanup();
}
void Echo::setpanning(const unsigned char & Ppanning)
void Echo::setpanning(const unsigned char &Ppanning)
{
this->Ppanning=Ppanning;
panning=(Ppanning+0.5)/127.0;
this->Ppanning = Ppanning;
panning = (Ppanning + 0.5) / 127.0;
}
void Echo::setdelay(const unsigned char & Pdelay)
void Echo::setdelay(const unsigned char &Pdelay)
{
delay.setmVal(Pdelay);
//this->Pdelay=Pdelay;
@@ -138,71 +146,76 @@ void Echo::setdelay(const unsigned char & Pdelay)
initdelays();
}
void Echo::setlrdelay(const unsigned char & Plrdelay)
void Echo::setlrdelay(const unsigned char &Plrdelay)
{
REALTYPE tmp;
this->Plrdelay=Plrdelay;
tmp=(pow(2,fabs(Plrdelay-64.0)/64.0*9)-1.0)/1000.0*SAMPLE_RATE;
if (Plrdelay<64.0) tmp=-tmp;
lrdelay=(int) tmp;
this->Plrdelay = Plrdelay;
tmp =
(pow(2, fabs(Plrdelay - 64.0) / 64.0 * 9) - 1.0) / 1000.0 * SAMPLE_RATE;
if(Plrdelay < 64.0)
tmp = -tmp;
lrdelay = (int) tmp;
initdelays();
}
void Echo::setlrcross(const unsigned char & Plrcross)
void Echo::setlrcross(const unsigned char &Plrcross)
{
this->Plrcross=Plrcross;
lrcross=Plrcross/127.0*1.0;
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0 * 1.0;
}
void Echo::setfb(const unsigned char & Pfb)
void Echo::setfb(const unsigned char &Pfb)
{
this->Pfb=Pfb;
fb=Pfb/128.0;
this->Pfb = Pfb;
fb = Pfb / 128.0;
}
void Echo::sethidamp(const unsigned char & Phidamp)
void Echo::sethidamp(const unsigned char &Phidamp)
{
this->Phidamp=Phidamp;
hidamp=1.0-Phidamp/127.0;
this->Phidamp = Phidamp;
hidamp = 1.0 - Phidamp / 127.0;
}
void Echo::setpreset(unsigned char npreset)
{
/**\todo see if the preset array can be replaced with a struct or a class*/
const int PRESET_SIZE=7;
const int NUM_PRESETS=9;
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
const int PRESET_SIZE = 7;
const int NUM_PRESETS = 9;
unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
//Echo 1
{67,64,35,64,30,59,0},
{67, 64, 35, 64, 30, 59, 0 },
//Echo 2
{67,64,21,64,30,59,0},
{67, 64, 21, 64, 30, 59, 0 },
//Echo 3
{67,75,60,64,30,59,10},
{67, 75, 60, 64, 30, 59, 10 },
//Simple Echo
{67,60,44,64,30,0,0},
{67, 60, 44, 64, 30, 0, 0 },
//Canyon
{67,60,102,50,30,82,48},
{67, 60, 102, 50, 30, 82, 48 },
//Panning Echo 1
{67,64,44,17,0,82,24},
{67, 64, 44, 17, 0, 82, 24 },
//Panning Echo 2
{81,60,46,118,100,68,18},
{81, 60, 46, 118, 100, 68, 18 },
//Panning Echo 3
{81,60,26,100,127,67,36},
{81, 60, 26, 100, 127, 67, 36 },
//Feedback Echo
{62,64,28,64,100,90,55}
{62, 64, 28, 64, 100, 90, 55 }
};
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
if (insertion) setvolume(presets[npreset][0]/2);//lower the volume if this is insertion effect
Ppreset=npreset;
if(npreset >= NUM_PRESETS)
npreset = NUM_PRESETS - 1;
for(int n = 0; n < PRESET_SIZE; n++)
changepar(n, presets[npreset][n]);
if(insertion)
setvolume(presets[npreset][0] / 2); //lower the volume if this is insertion effect
Ppreset = npreset;
}
void Echo::changepar(const int & npar,const unsigned char & value)
void Echo::changepar(const int &npar, const unsigned char &value)
{
switch (npar) {
switch(npar) {
case 0:
setvolume(value);
break;
@@ -224,34 +237,34 @@ void Echo::changepar(const int & npar,const unsigned char & value)
case 6:
sethidamp(value);
break;
};
}
}
unsigned char Echo::getpar(const int & npar)const
unsigned char Echo::getpar(const int &npar) const
{
switch (npar) {
switch(npar) {
case 0:
return(Pvolume);
return Pvolume;
break;
case 1:
return(Ppanning);
return Ppanning;
break;
case 2:
return(delay.getmVal());
return delay.getmVal();
break;
case 3:
return(Plrdelay);
return Plrdelay;
break;
case 4:
return(Plrcross);
return Plrcross;
break;
case 5:
return(Pfb);
return Pfb;
break;
case 6:
return(Phidamp);
return Phidamp;
break;
};
return(0);// in case of bogus parameter number
}
return 0; // in case of bogus parameter number
}

View File

@@ -32,105 +32,107 @@
/**Echo Effect*/
class Echo:public Effect
{
public:
public:
/**
* The Constructor For Echo
* @param insertion_ integer to determine if Echo is an insertion effect
* or not
* @param efxoutl_ Effect out Left Channel
* @param efxoutr_ Effect out Right Channel
* @return An initialized Echo Object
*/
Echo(const int & insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_);
/**
* The Constructor For Echo
* @param insertion_ integer to determine if Echo is an insertion effect
* or not
* @param efxoutl_ Effect out Left Channel
* @param efxoutr_ Effect out Right Channel
* @return An initialized Echo Object
*/
Echo(const int &insertion_,
REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_);
/**
* The destructor
*/
~Echo();
/**
* The destructor
*/
~Echo();
/**
* Outputs the echo to efxoutl and efxoutr
* @param smpsl Sample from Left channel
* @param smpsr Sample from Right channel
* \todo try to figure out if smpsl should be const *const
* or not (It should be)
*/
void out(REALTYPE *const smpsl,REALTYPE *const smpr);
void out(const Stereo<AuSample> &input);
/**
* Outputs the echo to efxoutl and efxoutr
* @param smpsl Sample from Left channel
* @param smpsr Sample from Right channel
* \todo try to figure out if smpsl should be const *const
* or not (It should be)
*/
void out(REALTYPE *const smpsl, REALTYPE *const smpr);
void out(const Stereo<AuSample> &input);
/**
* Sets the state of Echo to the specified preset
* @param npreset number of chosen preset
*/
void setpreset(unsigned char npreset);
/**
* Sets the state of Echo to the specified preset
* @param npreset number of chosen preset
*/
void setpreset(unsigned char npreset);
/**
* Sets the value of the chosen variable
*
* The possible parameters are:
* -# Volume
* -# Panning
* -# Delay
* -# L/R Delay
* -# L/R Crossover
* -# Feedback
* -# Dampening
* @param npar number of chosen parameter
* @param value the new value
*/
void changepar(const int & npar,const unsigned char & value);
/**
* Sets the value of the chosen variable
*
* The possible parameters are:
* -# Volume
* -# Panning
* -# Delay
* -# L/R Delay
* -# L/R Crossover
* -# Feedback
* -# Dampening
* @param npar number of chosen parameter
* @param value the new value
*/
void changepar(const int &npar, const unsigned char &value);
/**
* Gets the specified parameter
*
* The possible parameters are
* -# Volume
* -# Panning
* -# Delay
* -# L/R Delay
* -# L/R Crossover
* -# Feedback
* -# Dampening
* @param npar number of chosen parameter
* @return value of parameter
*/
unsigned char getpar(const int & npar)const;
/**
* Gets the specified parameter
*
* The possible parameters are
* -# Volume
* -# Panning
* -# Delay
* -# L/R Delay
* -# L/R Crossover
* -# Feedback
* -# Dampening
* @param npar number of chosen parameter
* @return value of parameter
*/
unsigned char getpar(const int &npar) const;
int getnumparams();
int getnumparams();
/**Zeros out the state of the Echo*/
void cleanup();
/**Zeros out the state of the Echo*/
void cleanup();
/**\todo This function needs to be implemented or the prototype should be removed*/
void setdryonly();
private:
//Parameters
char Pvolume;/**<#1 Volume or Dry/Wetness*/
char Ppanning;/**<#2 Panning*/
DelayCtl delay;/**<#3 Delay of the Echo*/
char Plrdelay;/**<#4 L/R delay difference*/
char Plrcross;/**<#5 L/R Mixing*/
char Pfb;/**<#6Feedback*/
char Phidamp;/**<#7Dampening of the Echo*/
/**\todo This function needs to be implemented or the prototype should be removed*/
void setdryonly();
private:
//Parameters
char Pvolume; /**<#1 Volume or Dry/Wetness*/
char Ppanning; /**<#2 Panning*/
DelayCtl delay; /**<#3 Delay of the Echo*/
char Plrdelay; /**<#4 L/R delay difference*/
char Plrcross; /**<#5 L/R Mixing*/
char Pfb; /**<#6Feedback*/
char Phidamp; /**<#7Dampening of the Echo*/
void setvolume(const unsigned char & Pvolume);
void setpanning(const unsigned char & Ppanning);
void setdelay(const unsigned char & Pdelay);
void setlrdelay(const unsigned char & Plrdelay);
void setlrcross(const unsigned char & Plrcross);
void setfb(const unsigned char & Pfb);
void sethidamp(const unsigned char & Phidamp);
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setdelay(const unsigned char &Pdelay);
void setlrdelay(const unsigned char &Plrdelay);
void setlrcross(const unsigned char &Plrcross);
void setfb(const unsigned char &Pfb);
void sethidamp(const unsigned char &Phidamp);
//Real Parameters
REALTYPE panning,lrcross,fb,hidamp; //needs better names
int dl,dr,lrdelay; //needs better names
//Real Parameters
REALTYPE panning, lrcross, fb, hidamp; //needs better names
int dl, dr, lrdelay; //needs better names
void initdelays();
Stereo<AuSample> delaySample;
Stereo<REALTYPE> old;
void initdelays();
Stereo<AuSample> delaySample;
Stereo<REALTYPE> old;
int kl,kr;
int kl, kr;
};
#endif

View File

@@ -23,8 +23,9 @@
#include "Effect.h"
Effect::Effect(bool insertion_,REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_,FilterParams *filterpars_,
const unsigned char & Ppreset_)
:Ppreset(Ppreset_),efxoutl(efxoutl_),efxoutr(efxoutr_),
filterpars(filterpars_),insertion(insertion_) {}
Effect::Effect(bool insertion_, REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_, FilterParams *filterpars_,
const unsigned char &Ppreset_)
:Ppreset(Ppreset_), efxoutl(efxoutl_), efxoutr(efxoutr_),
filterpars(filterpars_), insertion(insertion_) {}

View File

@@ -31,71 +31,71 @@
/**this class is inherited by the all effects(Reverb, Echo, ..)*/
class Effect
{
public:
/**
* Effect Constructor
* @param insertion_ 1 when it is an insertion Effect and 0 when it
* is not an insertion Effect
* @param efxoutl_ Effect output buffer Left channel
* @param efxoutr_ Effect output buffer Right channel
* @param filterpars_ pointer to FilterParams array
* @param Ppreset_ chosen preset
* @return Initialized Effect object*/
Effect(bool insertion_,REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_,FilterParams *filterpars_,
const unsigned char & Ppreset_);
/**Deconstructor
*
* Deconstructs the Effect and releases any resouces that it has
* allocated for itself*/
virtual ~Effect() {};
/**
* Choose a preset
* @param npreset number of chosen preset*/
virtual void setpreset(unsigned char npreset)=0;
/**Change parameter npar to value
* @param npar chosen parameter
* @param value chosen new value*/
virtual void changepar(const int &npar,const unsigned char &value)=0;
/**Get the value of parameter npar
* @param npar chosen parameter
* @return the value of the parameter in an unsigned char or 0 if it
* does not exist*/
virtual unsigned char getpar(const int &npar)const=0;
/**Output result of effect based on the given buffers
*
* This method should result in the effect generating its results
* and placing them into the efxoutl and efxoutr buffers.
* Every Effect should overide this method.
*
* @param smpsl Input buffer for the Left channel
* @param smpsr Input buffer for the Right channel
*/
virtual void out(REALTYPE *const smpsl,REALTYPE *const smpsr)=0;
/**Reset the state of the effect*/
virtual void cleanup() {};
/**This is only used for EQ (for user interface)*/
virtual REALTYPE getfreqresponse(REALTYPE freq) {
return (0);
};
public:
/**
* Effect Constructor
* @param insertion_ 1 when it is an insertion Effect and 0 when it
* is not an insertion Effect
* @param efxoutl_ Effect output buffer Left channel
* @param efxoutr_ Effect output buffer Right channel
* @param filterpars_ pointer to FilterParams array
* @param Ppreset_ chosen preset
* @return Initialized Effect object*/
Effect(bool insertion_, REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_, FilterParams *filterpars_,
const unsigned char &Ppreset_);
/**Deconstructor
*
* Deconstructs the Effect and releases any resouces that it has
* allocated for itself*/
virtual ~Effect() {}
/**
* Choose a preset
* @param npreset number of chosen preset*/
virtual void setpreset(unsigned char npreset) = 0;
/**Change parameter npar to value
* @param npar chosen parameter
* @param value chosen new value*/
virtual void changepar(const int &npar, const unsigned char &value) = 0;
/**Get the value of parameter npar
* @param npar chosen parameter
* @return the value of the parameter in an unsigned char or 0 if it
* does not exist*/
virtual unsigned char getpar(const int &npar) const = 0;
/**Output result of effect based on the given buffers
*
* This method should result in the effect generating its results
* and placing them into the efxoutl and efxoutr buffers.
* Every Effect should overide this method.
*
* @param smpsl Input buffer for the Left channel
* @param smpsr Input buffer for the Right channel
*/
virtual void out(REALTYPE *const smpsl, REALTYPE *const smpsr) = 0;
/**Reset the state of the effect*/
virtual void cleanup() {}
/**This is only used for EQ (for user interface)*/
virtual REALTYPE getfreqresponse(REALTYPE freq) {
return 0;
}
unsigned char Ppreset;/**<Currently used preset*/
REALTYPE *const efxoutl;/**<Effect out Left Channel*/
REALTYPE *const efxoutr;/**<Effect out Right Channel*/
/**\todo make efxoutl and efxoutr private and replace them with a StereoSample*/
unsigned char Ppreset; /**<Currently used preset*/
REALTYPE *const efxoutl; /**<Effect out Left Channel*/
REALTYPE *const efxoutr; /**<Effect out Right Channel*/
/**\todo make efxoutl and efxoutr private and replace them with a StereoSample*/
REALTYPE outvolume;/**<This is the volume of effect and is public because
REALTYPE outvolume;/**<This is the volume of effect and is public because
* it is needed in system effects.
* The out volume of such effects are always 1.0, so
* this setting tells me how is the volume to the
* Master Output only.*/
REALTYPE volume;
REALTYPE volume;
FilterParams *filterpars;/**<Parameters for filters used by Effect*/
protected:
FilterParams *filterpars; /**<Parameters for filters used by Effect*/
protected:
const bool insertion;/**<If Effect is an insertion effect, insertion=1
const bool insertion;/**<If Effect is an insertion effect, insertion=1
*otherwise, it should be insertion=0*/
};

View File

@@ -28,24 +28,23 @@
EffectLFO::EffectLFO()
{
xl=0.0;
xr=0.0;
Pfreq=40;
Prandomness=0;
PLFOtype=0;
Pstereo=96;
xl = 0.0;
xr = 0.0;
Pfreq = 40;
Prandomness = 0;
PLFOtype = 0;
Pstereo = 96;
updateparams();
ampl1=(1-lfornd)+lfornd*RND;
ampl2=(1-lfornd)+lfornd*RND;
ampr1=(1-lfornd)+lfornd*RND;
ampr2=(1-lfornd)+lfornd*RND;
};
ampl1 = (1 - lfornd) + lfornd * RND;
ampl2 = (1 - lfornd) + lfornd * RND;
ampr1 = (1 - lfornd) + lfornd * RND;
ampr2 = (1 - lfornd) + lfornd * RND;
}
EffectLFO::~EffectLFO()
{
};
{}
/*
@@ -53,19 +52,24 @@ EffectLFO::~EffectLFO()
*/
void EffectLFO::updateparams()
{
REALTYPE lfofreq=(pow(2,Pfreq/127.0*10.0)-1.0)*0.03;
incx=fabs(lfofreq)*(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE;
if (incx>0.49999999) incx=0.499999999; //Limit the Frequency
REALTYPE lfofreq = (pow(2, Pfreq / 127.0 * 10.0) - 1.0) * 0.03;
incx = fabs(lfofreq) * (REALTYPE)SOUND_BUFFER_SIZE / (REALTYPE)SAMPLE_RATE;
if(incx > 0.49999999)
incx = 0.499999999; //Limit the Frequency
lfornd=Prandomness/127.0;
if (lfornd<0.0) lfornd=0.0;
else if (lfornd>1.0) lfornd=1.0;
lfornd = Prandomness / 127.0;
if(lfornd < 0.0)
lfornd = 0.0;
else
if(lfornd > 1.0)
lfornd = 1.0;
if (PLFOtype>1) PLFOtype=1;//this has to be updated if more lfo's are added
lfotype=PLFOtype;
if(PLFOtype > 1)
PLFOtype = 1; //this has to be updated if more lfo's are added
lfotype = PLFOtype;
xr=fmod(xl+(Pstereo-64.0)/127.0+1.0,1.0);
};
xr = fmod(xl + (Pstereo - 64.0) / 127.0 + 1.0, 1.0);
}
/*
@@ -74,44 +78,50 @@ void EffectLFO::updateparams()
REALTYPE EffectLFO::getlfoshape(REALTYPE x)
{
REALTYPE out;
switch (lfotype) {
switch(lfotype) {
case 1: //EffectLFO_TRIANGLE
if ((x>0.0)&&(x<0.25)) out=4.0*x;
else if ((x>0.25)&&(x<0.75)) out=2-4*x;
else out=4.0*x-4.0;
if((x > 0.0) && (x < 0.25))
out = 4.0 * x;
else
if((x > 0.25) && (x < 0.75))
out = 2 - 4 * x;
else
out = 4.0 * x - 4.0;
break;
/**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/
/**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/
default:
out=cos(x*2*PI);//EffectLFO_SINE
};
return(out);
};
out = cos(x * 2 * PI); //EffectLFO_SINE
}
return out;
}
/*
* LFO output
*/
void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr)
void EffectLFO::effectlfoout(REALTYPE *outl, REALTYPE *outr)
{
REALTYPE out;
out=getlfoshape(xl);
if ((lfotype==0)||(lfotype==1)) out*=(ampl1+xl*(ampl2-ampl1));
xl+=incx;
if (xl>1.0) {
xl-=1.0;
ampl1=ampl2;
ampl2=(1.0-lfornd)+lfornd*RND;
};
*outl=(out+1.0)*0.5;
out = getlfoshape(xl);
if((lfotype == 0) || (lfotype == 1))
out *= (ampl1 + xl * (ampl2 - ampl1));
xl += incx;
if(xl > 1.0) {
xl -= 1.0;
ampl1 = ampl2;
ampl2 = (1.0 - lfornd) + lfornd * RND;
}
*outl = (out + 1.0) * 0.5;
out=getlfoshape(xr);
if ((lfotype==0)||(lfotype==1)) out*=(ampr1+xr*(ampr2-ampr1));
xr+=incx;
if (xr>1.0) {
xr-=1.0;
ampr1=ampr2;
ampr2=(1.0-lfornd)+lfornd*RND;
};
*outr=(out+1.0)*0.5;
};
out = getlfoshape(xr);
if((lfotype == 0) || (lfotype == 1))
out *= (ampr1 + xr * (ampr2 - ampr1));
xr += incx;
if(xr > 1.0) {
xr -= 1.0;
ampr1 = ampr2;
ampr2 = (1.0 - lfornd) + lfornd * RND;
}
*outr = (out + 1.0) * 0.5;
}

View File

@@ -28,24 +28,24 @@
* \todo see if this should inherit LFO*/
class EffectLFO
{
public:
EffectLFO();
~EffectLFO();
void effectlfoout(REALTYPE *outl,REALTYPE *outr);
void updateparams();
unsigned char Pfreq;
unsigned char Prandomness;
unsigned char PLFOtype;
unsigned char Pstereo;//"64"=0
private:
REALTYPE getlfoshape(REALTYPE x);
public:
EffectLFO();
~EffectLFO();
void effectlfoout(REALTYPE *outl, REALTYPE *outr);
void updateparams();
unsigned char Pfreq;
unsigned char Prandomness;
unsigned char PLFOtype;
unsigned char Pstereo; //"64"=0
private:
REALTYPE getlfoshape(REALTYPE x);
REALTYPE xl,xr;
REALTYPE incx;
REALTYPE ampl1,ampl2,ampr1,ampr2;//necessary for "randomness"
REALTYPE lfointensity;
REALTYPE lfornd;
char lfotype; /**\todo GET RID OF CHAR (replace with short or enum)*/
REALTYPE xl, xr;
REALTYPE incx;
REALTYPE ampl1, ampl2, ampr1, ampr2; //necessary for "randomness"
REALTYPE lfointensity;
REALTYPE lfornd;
char lfotype; /**\todo GET RID OF CHAR (replace with short or enum)*/
};

View File

@@ -22,11 +22,11 @@
#include "EffectMgr.h"
EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_)
:insertion(insertion_),
efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]),
efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]),
filterpars(NULL),nefx(0),efx(NULL),mutex(mutex_),dryonly(false)
EffectMgr::EffectMgr(int insertion_, pthread_mutex_t *mutex_)
:insertion(insertion_),
efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]),
efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]),
filterpars(NULL), nefx(0), efx(NULL), mutex(mutex_), dryonly(false)
{
setpresettype("Peffect"); /**\todo Figure out what this is doing
* , as it might be another leaky abstraction.*/
@@ -36,10 +36,10 @@ EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_)
// mutex=mutex_;
// efxoutl=new REALTYPE[SOUND_BUFFER_SIZE];
// efxoutr=new REALTYPE[SOUND_BUFFER_SIZE];
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
efxoutl[i]=0.0;
efxoutr[i]=0.0;
};
for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] = 0.0;
efxoutr[i] = 0.0;
}
// filterpars=NULL;
// dryonly=false;
defaults();
@@ -48,9 +48,10 @@ EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_)
EffectMgr::~EffectMgr()
{
if (efx!=NULL) delete efx;
delete []efxoutl;
delete []efxoutr;
if(efx != NULL)
delete efx;
delete [] efxoutl;
delete [] efxoutr;
}
void EffectMgr::defaults()
@@ -65,46 +66,49 @@ void EffectMgr::defaults()
void EffectMgr::changeeffect(int nefx_)
{
cleanup();
if (nefx==nefx_) return;
nefx=nefx_;
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
efxoutl[i]=0.0;
efxoutr[i]=0.0;
};
if(nefx == nefx_)
return;
nefx = nefx_;
for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] = 0.0;
efxoutr[i] = 0.0;
}
if (efx!=NULL) delete efx;
switch (nefx) { /**\todo replace leaky abstraction*/
if(efx != NULL)
delete efx;
switch(nefx) { /**\todo replace leaky abstraction*/
case 1:
efx=new Reverb(insertion,efxoutl,efxoutr);
efx = new Reverb(insertion, efxoutl, efxoutr);
break;
case 2:
efx=new Echo(insertion,efxoutl,efxoutr);
efx = new Echo(insertion, efxoutl, efxoutr);
break;
case 3:
efx=new Chorus(insertion,efxoutl,efxoutr);
efx = new Chorus(insertion, efxoutl, efxoutr);
break;
case 4:
efx=new Phaser(insertion,efxoutl,efxoutr);
efx = new Phaser(insertion, efxoutl, efxoutr);
break;
case 5:
efx=new Alienwah(insertion,efxoutl,efxoutr);
efx = new Alienwah(insertion, efxoutl, efxoutr);
break;
case 6:
efx=new Distorsion(insertion,efxoutl,efxoutr);
efx = new Distorsion(insertion, efxoutl, efxoutr);
break;
case 7:
efx=new EQ(insertion,efxoutl,efxoutr);
efx = new EQ(insertion, efxoutl, efxoutr);
break;
case 8:
efx=new DynamicFilter(insertion,efxoutl,efxoutr);
efx = new DynamicFilter(insertion, efxoutl, efxoutr);
break;
//put more effect here
//put more effect here
default:
efx=NULL;
break;//no effect (thru)
};
efx = NULL;
break; //no effect (thru)
}
if (efx!=NULL) filterpars=efx->filterpars;
if(efx != NULL)
filterpars = efx->filterpars;
}
/*
@@ -112,7 +116,7 @@ void EffectMgr::changeeffect(int nefx_)
*/
int EffectMgr::geteffect()
{
return (nefx);
return nefx;
}
/*
@@ -120,7 +124,8 @@ int EffectMgr::geteffect()
*/
void EffectMgr::cleanup()
{
if (efx!=NULL) efx->cleanup();
if(efx != NULL)
efx->cleanup();
}
@@ -130,8 +135,10 @@ void EffectMgr::cleanup()
unsigned char EffectMgr::getpreset()
{
if (efx!=NULL) return(efx->Ppreset);
else return(0);
if(efx != NULL)
return efx->Ppreset;
else
return 0;
}
/*
@@ -139,7 +146,8 @@ unsigned char EffectMgr::getpreset()
*/
void EffectMgr::changepreset_nolock(unsigned char npreset)
{
if (efx!=NULL) efx->setpreset(npreset);
if(efx != NULL)
efx->setpreset(npreset);
}
/*
@@ -156,19 +164,20 @@ void EffectMgr::changepreset(unsigned char npreset)
/*
* Change a parameter of the current effect
*/
void EffectMgr::seteffectpar_nolock(int npar,unsigned char value)
void EffectMgr::seteffectpar_nolock(int npar, unsigned char value)
{
if (efx==NULL) return;
efx->changepar(npar,value);
if(efx == NULL)
return;
efx->changepar(npar, value);
}
/*
* Change a parameter of the current effect (with thread locking)
*/
void EffectMgr::seteffectpar(int npar,unsigned char value)
void EffectMgr::seteffectpar(int npar, unsigned char value)
{
pthread_mutex_lock(mutex);
seteffectpar_nolock(npar,value);
seteffectpar_nolock(npar, value);
pthread_mutex_unlock(mutex);
}
@@ -177,80 +186,85 @@ void EffectMgr::seteffectpar(int npar,unsigned char value)
*/
unsigned char EffectMgr::geteffectpar(int npar)
{
if (efx==NULL) return(0);
return(efx->getpar(npar));
if(efx == NULL)
return 0;
return efx->getpar(npar);
}
/*
* Apply the effect
*/
void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr)
void EffectMgr::out(REALTYPE *smpsl, REALTYPE *smpsr)
{
int i;
if (efx==NULL) {
if (insertion==0)
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
smpsl[i]=0.0;
smpsr[i]=0.0;
efxoutl[i]=0.0;
efxoutr[i]=0.0;
};
if(efx == NULL) {
if(insertion == 0)
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
smpsl[i] = 0.0;
smpsr[i] = 0.0;
efxoutl[i] = 0.0;
efxoutr[i] = 0.0;
}
;
return;
};
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
smpsl[i]+=denormalkillbuf[i];
smpsr[i]+=denormalkillbuf[i];
efxoutl[i]=0.0;
efxoutr[i]=0.0;
};
efx->out(smpsl,smpsr);
}
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
smpsl[i] += denormalkillbuf[i];
smpsr[i] += denormalkillbuf[i];
efxoutl[i] = 0.0;
efxoutr[i] = 0.0;
}
efx->out(smpsl, smpsr);
REALTYPE volume=efx->volume;
REALTYPE volume = efx->volume;
if (nefx==7) {//this is need only for the EQ effect
if(nefx == 7) { //this is need only for the EQ effect
/**\todo figure out why*/
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
smpsl[i]=efxoutl[i];
smpsr[i]=efxoutr[i];
};
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
smpsl[i] = efxoutl[i];
smpsr[i] = efxoutr[i];
}
return;
};
}
//Insertion effect
if (insertion!=0) {
REALTYPE v1,v2;
if (volume<0.5) {
v1=1.0;
v2=volume*2.0;
} else {
v1=(1.0-volume)*2.0;
v2=1.0;
};
if ((nefx==1)||(nefx==2)) v2*=v2;//for Reverb and Echo, the wet function is not liniar
if (dryonly) {//this is used for instrument effect only
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
smpsl[i]*=v1;
smpsr[i]*=v1;
efxoutl[i]*=v2;
efxoutr[i]*=v2;
};
} else {//normal instrument/insertion effect
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
smpsl[i]=smpsl[i]*v1+efxoutl[i]*v2;
smpsr[i]=smpsr[i]*v1+efxoutr[i]*v2;
};
};
} else {//System effect
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
efxoutl[i]*=2.0*volume;
efxoutr[i]*=2.0*volume;
smpsl[i]=efxoutl[i];
smpsr[i]=efxoutr[i];
};
};
if(insertion != 0) {
REALTYPE v1, v2;
if(volume < 0.5) {
v1 = 1.0;
v2 = volume * 2.0;
}
else {
v1 = (1.0 - volume) * 2.0;
v2 = 1.0;
}
if((nefx == 1) || (nefx == 2))
v2 *= v2; //for Reverb and Echo, the wet function is not liniar
if(dryonly) { //this is used for instrument effect only
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
smpsl[i] *= v1;
smpsr[i] *= v1;
efxoutl[i] *= v2;
efxoutr[i] *= v2;
}
}
else { //normal instrument/insertion effect
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
smpsl[i] = smpsl[i] * v1 + efxoutl[i] * v2;
smpsr[i] = smpsr[i] * v1 + efxoutr[i] * v2;
}
}
}
else { //System effect
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] *= 2.0 * volume;
efxoutr[i] *= 2.0 * volume;
smpsl[i] = efxoutl[i];
smpsr[i] = efxoutr[i];
}
}
}
/*
@@ -258,8 +272,10 @@ void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr)
*/
REALTYPE EffectMgr::sysefxgetvolume()
{
if (efx==NULL) return (1.0);
else return(efx->outvolume);
if(efx == NULL)
return 1.0;
else
return efx->outvolume;
}
@@ -268,65 +284,72 @@ REALTYPE EffectMgr::sysefxgetvolume()
*/
REALTYPE EffectMgr::getEQfreqresponse(REALTYPE freq)
{
if (nefx==7) return(efx->getfreqresponse(freq));
else return(0.0);
if(nefx == 7)
return efx->getfreqresponse(freq);
else
return 0.0;
}
void EffectMgr::setdryonly(bool value)
{
dryonly=value;
dryonly = value;
}
void EffectMgr::add2XML(XMLwrapper *xml)
{
xml->addpar("type",geteffect());
xml->addpar("type", geteffect());
if ((efx==NULL)||(geteffect()==0)) return;
xml->addpar("preset",efx->Ppreset);
if((efx == NULL) || (geteffect() == 0))
return;
xml->addpar("preset", efx->Ppreset);
xml->beginbranch("EFFECT_PARAMETERS");
for (int n=0;n<128;n++) { /**\todo evaluate who should oversee saving
* and loading of parameters*/
int par=geteffectpar(n);
if (par==0) continue;
xml->beginbranch("par_no",n);
xml->addpar("par",par);
for(int n = 0; n < 128; n++) {
/**\todo evaluate who should oversee saving
* and loading of parameters*/
int par = geteffectpar(n);
if(par == 0)
continue;
xml->beginbranch("par_no", n);
xml->addpar("par", par);
xml->endbranch();
};
if (filterpars!=NULL) {
}
if(filterpars != NULL) {
xml->beginbranch("FILTER");
filterpars->add2XML(xml);
xml->endbranch();
};
}
xml->endbranch();
}
void EffectMgr::getfromXML(XMLwrapper *xml)
{
changeeffect(xml->getpar127("type",geteffect()));
changeeffect(xml->getpar127("type", geteffect()));
if ((efx==NULL)||(geteffect()==0)) return;
if((efx == NULL) || (geteffect() == 0))
return;
efx->Ppreset=xml->getpar127("preset",efx->Ppreset);
efx->Ppreset = xml->getpar127("preset", efx->Ppreset);
if (xml->enterbranch("EFFECT_PARAMETERS")) {
for (int n=0;n<128;n++) {
seteffectpar_nolock(n,0);//erase effect parameter
if (xml->enterbranch("par_no",n)==0) continue;
if(xml->enterbranch("EFFECT_PARAMETERS")) {
for(int n = 0; n < 128; n++) {
seteffectpar_nolock(n, 0); //erase effect parameter
if(xml->enterbranch("par_no", n) == 0)
continue;
int par=geteffectpar(n);
seteffectpar_nolock(n,xml->getpar127("par",par));
int par = geteffectpar(n);
seteffectpar_nolock(n, xml->getpar127("par", par));
xml->exitbranch();
};
if (filterpars!=NULL) {
if (xml->enterbranch("FILTER")) {
}
if(filterpars != NULL) {
if(xml->enterbranch("FILTER")) {
filterpars->getfromXML(xml);
xml->exitbranch();
};
};
}
}
xml->exitbranch();
};
}
cleanup();
}

View File

@@ -41,62 +41,62 @@
/**Effect manager, an interface betwen the program and effects*/
class EffectMgr:public Presets
{
public:
EffectMgr(int insertion_,pthread_mutex_t *mutex_);
~EffectMgr();
public:
EffectMgr(int insertion_, pthread_mutex_t *mutex_);
~EffectMgr();
void add2XML(XMLwrapper *xml);
void defaults();
void getfromXML(XMLwrapper *xml);
void add2XML(XMLwrapper *xml);
void defaults();
void getfromXML(XMLwrapper *xml);
void out(REALTYPE *smpsl,REALTYPE *smpsr);
void out(REALTYPE *smpsl, REALTYPE *smpsr);
void setdryonly(bool value);
void setdryonly(bool value);
/**get the output(to speakers) volume of the systemeffect*/
REALTYPE sysefxgetvolume();
/**get the output(to speakers) volume of the systemeffect*/
REALTYPE sysefxgetvolume();
void cleanup();/**<cleanup the effect*/
void cleanup(); /**<cleanup the effect*/
/**change effect to the given int
* @param nefx_ the number of the effect*/
void changeeffect(int nefx_);
/**Get the number of the effect
* @return the number*/
int geteffect();
/**
* Change the preset to the given one
* @param npreset number of the chosen preset
*/
void changepreset(unsigned char npreset);
/**
* Change the preset to the given one without locking the thread
* @param npreset number of the chosen preset
*/
void changepreset_nolock(unsigned char npreset);
/**
* Get the current preset
* @return the current preset*/
unsigned char getpreset();
/**sets the effect par*/
void seteffectpar(int npar,unsigned char value);
/**<sets the effect par without thread lock*/
void seteffectpar_nolock(int npar,unsigned char value);
unsigned char geteffectpar(int npar);
const bool insertion;/**<1 if the effect is connected as insertion effect*/
REALTYPE *efxoutl,*efxoutr;
/**change effect to the given int
* @param nefx_ the number of the effect*/
void changeeffect(int nefx_);
/**Get the number of the effect
* @return the number*/
int geteffect();
/**
* Change the preset to the given one
* @param npreset number of the chosen preset
*/
void changepreset(unsigned char npreset);
/**
* Change the preset to the given one without locking the thread
* @param npreset number of the chosen preset
*/
void changepreset_nolock(unsigned char npreset);
/**
* Get the current preset
* @return the current preset*/
unsigned char getpreset();
/**sets the effect par*/
void seteffectpar(int npar, unsigned char value);
/**<sets the effect par without thread lock*/
void seteffectpar_nolock(int npar, unsigned char value);
unsigned char geteffectpar(int npar);
const bool insertion; /**<1 if the effect is connected as insertion effect*/
REALTYPE *efxoutl, *efxoutr;
/**used by UI
* \todo needs to be decoupled*/
REALTYPE getEQfreqresponse(REALTYPE freq);
/**used by UI
* \todo needs to be decoupled*/
REALTYPE getEQfreqresponse(REALTYPE freq);
FilterParams *filterpars;
FilterParams *filterpars;
private:
int nefx;
Effect *efx;
pthread_mutex_t *mutex;
bool dryonly;
private:
int nefx;
Effect *efx;
pthread_mutex_t *mutex;
bool dryonly;
};
#endif

View File

@@ -1,283 +1,294 @@
/*
ZynAddSubFX - a software synthesizer
Phaser.C - Phaser effect
Copyright (C) 2002-2005 Nasca Octavian Paul
Author: Nasca Octavian Paul
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 "Phaser.h"
#define PHASER_LFO_SHAPE 2
Phaser::Phaser(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0),old(1),oldgain(0.0)
{
setpreset(Ppreset);
cleanup();
};
Phaser::~Phaser()
{
};
/*
* Effect output
*/
void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr)
{
int i,j;
REALTYPE lfol,lfor,lgain,rgain,tmp;
lfo.effectlfoout(&lfol,&lfor);
lgain=lfol;
rgain=lfor;
lgain=(exp(lgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0);
rgain=(exp(rgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0);
lgain=1.0-phase*(1.0-depth)-(1.0-phase)*lgain*depth;
rgain=1.0-phase*(1.0-depth)-(1.0-phase)*rgain*depth;
if (lgain>1.0) lgain=1.0;
else if (lgain<0.0) lgain=0.0;
if (rgain>1.0) rgain=1.0;
else if (rgain<0.0) rgain=0.0;
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
REALTYPE x=(REALTYPE) i /SOUND_BUFFER_SIZE;
REALTYPE x1=1.0-x;
REALTYPE gl=lgain*x+oldgain.left()*x1;
REALTYPE gr=rgain*x+oldgain.right()*x1;
REALTYPE inl=smpsl[i]*panning+fbl;
REALTYPE inr=smpsr[i]*(1.0-panning)+fbr;
//Left channel
for (j=0;j<Pstages*2;j++) {//Phasing routine
tmp=old.left()[j];
old.left()[j]=gl*tmp+inl;
inl=tmp-gl*old.left()[j];
};
//Right channel
for (j=0;j<Pstages*2;j++) {//Phasing routine
tmp=old.right()[j];
old.right()[j]=gr*tmp+inr;
inr=tmp-gr*old.right()[j];
};
//Left/Right crossing
REALTYPE l=inl;
REALTYPE r=inr;
inl=l*(1.0-lrcross)+r*lrcross;
inr=r*(1.0-lrcross)+l*lrcross;
fbl=inl*fb;
fbr=inr*fb;
efxoutl[i]=inl;
efxoutr[i]=inr;
};
oldgain=Stereo<REALTYPE>(lgain,rgain);
if (Poutsub!=0)
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
efxoutl[i]*= -1.0;
efxoutr[i]*= -1.0;
};
};
/*
* Cleanup the effect
*/
void Phaser::cleanup()
{
fbl=0.0;
fbr=0.0;
oldgain=Stereo<REALTYPE>(0.0);
old.l().clear();
old.r().clear();
};
/*
* Parameter control
*/
void Phaser::setdepth(const unsigned char &Pdepth)
{
this->Pdepth=Pdepth;
depth=(Pdepth/127.0);
};
void Phaser::setfb(const unsigned char &Pfb)
{
this->Pfb=Pfb;
fb=(Pfb-64.0)/64.1;
};
void Phaser::setvolume(const unsigned char &Pvolume)
{
this->Pvolume=Pvolume;
outvolume=Pvolume/127.0;
if (insertion==0) volume=1.0;
else volume=outvolume;
};
void Phaser::setpanning(const unsigned char &Ppanning)
{
this->Ppanning=Ppanning;
panning=Ppanning/127.0;
};
void Phaser::setlrcross(const unsigned char &Plrcross)
{
this->Plrcross=Plrcross;
lrcross=Plrcross/127.0;
};
void Phaser::setstages(const unsigned char &Pstages)
{
if (Pstages>=MAX_PHASER_STAGES) this->Pstages=MAX_PHASER_STAGES-1;
else this->Pstages=Pstages;
old=Stereo<AuSample>(Pstages*2);
cleanup();
};
void Phaser::setphase(const unsigned char &Pphase)
{
this->Pphase=Pphase;
phase=(Pphase/127.0);
};
void Phaser::setpreset(unsigned char npreset)
{
const int PRESET_SIZE=12;
const int NUM_PRESETS=6;
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
//Phaser1
{64,64,36,0,0,64,110,64,1,0,0,20},
//Phaser2
{64,64,35,0,0,88,40,64,3,0,0,20},
//Phaser3
{64,64,31,0,0,66,68,107,2,0,0,20},
//Phaser4
{39,64,22,0,0,66,67,10,5,0,1,20},
//Phaser5
{64,64,20,0,1,110,67,78,10,0,0,20},
//Phaser6
{64,64,53,100,0,58,37,78,3,0,0,20}
};
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
Ppreset=npreset;
};
void Phaser::changepar(const int &npar,const 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;
};
};
unsigned char Phaser::getpar(const 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);
};
};
/*
ZynAddSubFX - a software synthesizer
Phaser.C - Phaser effect
Copyright (C) 2002-2005 Nasca Octavian Paul
Author: Nasca Octavian Paul
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 "Phaser.h"
#define PHASER_LFO_SHAPE 2
Phaser::Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), old(1), oldgain(0.0)
{
setpreset(Ppreset);
cleanup();
}
Phaser::~Phaser()
{}
/*
* Effect output
*/
void Phaser::out(REALTYPE *smpsl, REALTYPE *smpsr)
{
int i, j;
REALTYPE lfol, lfor, lgain, rgain, tmp;
lfo.effectlfoout(&lfol, &lfor);
lgain = lfol;
rgain = lfor;
lgain = (exp(lgain * PHASER_LFO_SHAPE) - 1) / (exp(PHASER_LFO_SHAPE) - 1.0);
rgain = (exp(rgain * PHASER_LFO_SHAPE) - 1) / (exp(PHASER_LFO_SHAPE) - 1.0);
lgain = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * lgain * depth;
rgain = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * rgain * depth;
if(lgain > 1.0)
lgain = 1.0;
else
if(lgain < 0.0)
lgain = 0.0;
if(rgain > 1.0)
rgain = 1.0;
else
if(rgain < 0.0)
rgain = 0.0;
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
REALTYPE x = (REALTYPE) i / SOUND_BUFFER_SIZE;
REALTYPE x1 = 1.0 - x;
REALTYPE gl = lgain * x + oldgain.left() * x1;
REALTYPE gr = rgain * x + oldgain.right() * x1;
REALTYPE inl = smpsl[i] * panning + fbl;
REALTYPE inr = smpsr[i] * (1.0 - panning) + fbr;
//Left channel
for(j = 0; j < Pstages * 2; j++) { //Phasing routine
tmp = old.left()[j];
old.left()[j] = gl * tmp + inl;
inl = tmp - gl *old.left()[j];
}
//Right channel
for(j = 0; j < Pstages * 2; j++) { //Phasing routine
tmp = old.right()[j];
old.right()[j] = gr * tmp + inr;
inr = tmp - gr *old.right()[j];
}
//Left/Right crossing
REALTYPE l = inl;
REALTYPE r = inr;
inl = l * (1.0 - lrcross) + r * lrcross;
inr = r * (1.0 - lrcross) + l * lrcross;
fbl = inl * fb;
fbr = inr * fb;
efxoutl[i] = inl;
efxoutr[i] = inr;
}
oldgain = Stereo<REALTYPE>(lgain, rgain);
if(Poutsub != 0)
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] *= -1.0;
efxoutr[i] *= -1.0;
}
;
}
/*
* Cleanup the effect
*/
void Phaser::cleanup()
{
fbl = 0.0;
fbr = 0.0;
oldgain = Stereo<REALTYPE>(0.0);
old.l().clear();
old.r().clear();
}
/*
* Parameter control
*/
void Phaser::setdepth(const unsigned char &Pdepth)
{
this->Pdepth = Pdepth;
depth = (Pdepth / 127.0);
}
void Phaser::setfb(const unsigned char &Pfb)
{
this->Pfb = Pfb;
fb = (Pfb - 64.0) / 64.1;
}
void Phaser::setvolume(const unsigned char &Pvolume)
{
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
if(insertion == 0)
volume = 1.0;
else
volume = outvolume;
}
void Phaser::setpanning(const unsigned char &Ppanning)
{
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
void Phaser::setlrcross(const unsigned char &Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0;
}
void Phaser::setstages(const unsigned char &Pstages)
{
if(Pstages >= MAX_PHASER_STAGES)
this->Pstages = MAX_PHASER_STAGES - 1;
else
this->Pstages = Pstages;
old = Stereo<AuSample>(Pstages * 2);
cleanup();
}
void Phaser::setphase(const unsigned char &Pphase)
{
this->Pphase = Pphase;
phase = (Pphase / 127.0);
}
void Phaser::setpreset(unsigned char npreset)
{
const int PRESET_SIZE = 12;
const int NUM_PRESETS = 6;
unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
//Phaser1
{64, 64, 36, 0, 0, 64, 110, 64, 1, 0, 0, 20},
//Phaser2
{64, 64, 35, 0, 0, 88, 40, 64, 3, 0, 0, 20},
//Phaser3
{64, 64, 31, 0, 0, 66, 68, 107, 2, 0, 0, 20},
//Phaser4
{39, 64, 22, 0, 0, 66, 67, 10, 5, 0, 1, 20},
//Phaser5
{64, 64, 20, 0, 1, 110, 67, 78, 10, 0, 0, 20},
//Phaser6
{64, 64, 53, 100, 0, 58, 37, 78, 3, 0, 0, 20}
};
if(npreset >= NUM_PRESETS)
npreset = NUM_PRESETS - 1;
for(int n = 0; n < PRESET_SIZE; n++)
changepar(n, presets[npreset][n]);
Ppreset = npreset;
}
void Phaser::changepar(const int &npar, const 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;
}
}
unsigned char Phaser::getpar(const 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;
}
}

View File

@@ -1,76 +1,76 @@
/*
ZynAddSubFX - a software synthesizer
Phaser.h - Phaser effect
Copyright (C) 2002-2005 Nasca Octavian Paul
Author: Nasca Octavian Paul
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 PHASER_H
#define PHASER_H
#include "../globals.h"
#include "../Misc/Stereo.h"
#include "../Samples/AuSample.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();
void out(REALTYPE *smpsl,REALTYPE *smpsr);
void setpreset(unsigned char npreset);
void changepar(const int &npar,const unsigned char &value);
unsigned char getpar(const int &npar)const;
void cleanup();
void setdryonly();
private:
//Parametrii Phaser
EffectLFO lfo;/**<lfo-ul Phaser*/
unsigned char Pvolume;
unsigned char Ppanning;
unsigned char Pdepth;/**<the depth of the Phaser*/
unsigned char Pfb;/**<feedback*/
unsigned char Plrcross;/**<feedback*/
unsigned char Pstages;
unsigned char Poutsub;/**<if I wish to substract the output instead of the adding it*/
unsigned char Pphase;
//Control Parametrii
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setdepth(const unsigned char &Pdepth);
void setfb(const unsigned char &Pfb);
void setlrcross(const unsigned char &Plrcross);
void setstages(const unsigned char &Pstages);
void setphase(const unsigned char &Pphase);
//Internal Values
//int insertion; //inherited from Effect
REALTYPE panning,fb,depth,lrcross,fbl,fbr,phase;
//REALTYPE *oldl,*oldr;
Stereo<AuSample> old;
//REALTYPE oldlgain,oldrgain;
Stereo<REALTYPE> oldgain;
};
#endif
/*
ZynAddSubFX - a software synthesizer
Phaser.h - Phaser effect
Copyright (C) 2002-2005 Nasca Octavian Paul
Author: Nasca Octavian Paul
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 PHASER_H
#define PHASER_H
#include "../globals.h"
#include "../Misc/Stereo.h"
#include "../Samples/AuSample.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();
void out(REALTYPE *smpsl, REALTYPE *smpsr);
void setpreset(unsigned char npreset);
void changepar(const int &npar, const unsigned char &value);
unsigned char getpar(const int &npar) const;
void cleanup();
void setdryonly();
private:
//Parametrii Phaser
EffectLFO lfo; /**<lfo-ul Phaser*/
unsigned char Pvolume;
unsigned char Ppanning;
unsigned char Pdepth; /**<the depth of the Phaser*/
unsigned char Pfb; /**<feedback*/
unsigned char Plrcross; /**<feedback*/
unsigned char Pstages;
unsigned char Poutsub; /**<if I wish to substract the output instead of the adding it*/
unsigned char Pphase;
//Control Parametrii
void setvolume(const unsigned char &Pvolume);
void setpanning(const unsigned char &Ppanning);
void setdepth(const unsigned char &Pdepth);
void setfb(const unsigned char &Pfb);
void setlrcross(const unsigned char &Plrcross);
void setstages(const unsigned char &Pstages);
void setphase(const unsigned char &Pphase);
//Internal Values
//int insertion; //inherited from Effect
REALTYPE panning, fb, depth, lrcross, fbl, fbr, phase;
//REALTYPE *oldl,*oldr;
Stereo<AuSample> old;
//REALTYPE oldlgain,oldrgain;
Stereo<REALTYPE> oldgain;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,127 +1,135 @@
/*
ZynAddSubFX - a software synthesizer
Reverb.h - Reverberation effect
Copyright (C) 2002-2005 Nasca Octavian Paul
Author: Nasca Octavian Paul
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 REVERB_H
#define REVERB_H
#include "../globals.h"
#include "../DSP/AnalogFilter.h"
#include "Effect.h"
#define REV_COMBS 8
#define REV_APS 4
/**Creates Reverberation Effects*/
class Reverb:public Effect
{
public:
Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
~Reverb();
void out(REALTYPE *smps_l,REALTYPE *smps_r);
void cleanup();
void setpreset(unsigned char npreset);
void changepar(const int &npar,const unsigned char &value);
unsigned char getpar(const int &npar)const;
private:
//Parametrii
/**Amount of the reverb*/
unsigned char Pvolume;
/**Left/Right Panning*/
unsigned char Ppan;
/**duration of reverb*/
unsigned char Ptime;
/**Initial delay*/
unsigned char Pidelay;
/**Initial delay feedback*/
unsigned char Pidelayfb;
/**delay between ER/Reverbs*/
unsigned char Prdelay;
/**EarlyReflections/Reverb Balance*/
unsigned char Perbalance;
/**HighPassFilter*/
unsigned char Plpf;
/**LowPassFilter*/
unsigned char Phpf;
/**Low/HighFrequency Damping
* \todo 0..63 lpf,64=off,65..127=hpf(TODO)*/
unsigned char Plohidamp;
/**Reverb type*/
unsigned char Ptype;
/**Room Size*/
unsigned char Proomsize;
//parameter control
void setvolume(const unsigned char &Pvolume);
void setpan(const unsigned char &Ppan);
void settime(const unsigned char &Ptime);
void setlohidamp(unsigned char Plohidamp);
void setidelay(const unsigned char &Pidelay);
void setidelayfb(const unsigned char &Pidelayfb);
void sethpf(const unsigned char &Phpf);
void setlpf(const unsigned char &Plpf);
void settype( unsigned char Ptype);
void setroomsize(const unsigned char &Proomsize);
REALTYPE pan,erbalance;
//Parametrii 2
int lohidamptype;/**<0=disable,1=highdamp(lowpass),2=lowdamp(highpass)*/
int idelaylen,rdelaylen;
int idelayk;
REALTYPE lohifb,idelayfb,roomsize,rs;//rs is used to "normalise" the volume according to the roomsize
int comblen[REV_COMBS*2];
int aplen[REV_APS*2];
//Internal Variables
REALTYPE *comb[REV_COMBS*2];
int combk[REV_COMBS*2];
REALTYPE combfb[REV_COMBS*2];/**<feedback-ul fiecarui filtru "comb"*/
REALTYPE lpcomb[REV_COMBS*2];/**<pentru Filtrul LowPass*/
REALTYPE *ap[REV_APS*2];
int apk[REV_APS*2];
REALTYPE *idelay;
AnalogFilter *lpf,*hpf;//filters
REALTYPE *inputbuf;
void processmono(int ch,REALTYPE *output);
};
#endif
/*
ZynAddSubFX - a software synthesizer
Reverb.h - Reverberation effect
Copyright (C) 2002-2009 Nasca Octavian Paul
Author: Nasca Octavian Paul
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 REVERB_H
#define REVERB_H
#include <math.h>
#include "../globals.h"
#include "../DSP/AnalogFilter.h"
#include "../DSP/FFTwrapper.h"
#include "../DSP/Unison.h"
#include "Effect.h"
#define REV_COMBS 8
#define REV_APS 4
/**Creates Reverberation Effects*/
class Reverb:public Effect
{
public:
Reverb(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~Reverb();
void out(REALTYPE *smps_l, REALTYPE *smps_r);
void cleanup();
void setpreset(unsigned char npreset);
void changepar(const int &npar, const unsigned char &value);
unsigned char getpar(const int &npar) const;
private:
//Parametrii
/**Amount of the reverb*/
unsigned char Pvolume;
/**Left/Right Panning*/
unsigned char Ppan;
/**duration of reverb*/
unsigned char Ptime;
/**Initial delay*/
unsigned char Pidelay;
/**Initial delay feedback*/
unsigned char Pidelayfb;
/**delay between ER/Reverbs*/
unsigned char Prdelay;
/**EarlyReflections/Reverb Balance*/
unsigned char Perbalance;
/**HighPassFilter*/
unsigned char Plpf;
/**LowPassFilter*/
unsigned char Phpf;
/**Low/HighFrequency Damping
* \todo 0..63 lpf,64=off,65..127=hpf(TODO)*/
unsigned char Plohidamp;
/**Reverb type*/
unsigned char Ptype;
/**Room Size*/
unsigned char Proomsize;
/**Bandwidth */
unsigned char Pbandwidth;
//parameter control
void setvolume(const unsigned char &Pvolume);
void setpan(const unsigned char &Ppan);
void settime(const unsigned char &Ptime);
void setlohidamp(unsigned char Plohidamp);
void setidelay(const unsigned char &Pidelay);
void setidelayfb(const unsigned char &Pidelayfb);
void sethpf(const unsigned char &Phpf);
void setlpf(const unsigned char &Plpf);
void settype(unsigned char Ptype);
void setroomsize(const unsigned char &Proomsize);
void setbandwidth(const unsigned char &Pbandwidth);
REALTYPE pan, erbalance;
//Parameters
int lohidamptype; /**<0=disable,1=highdamp(lowpass),2=lowdamp(highpass)*/
int idelaylen, rdelaylen;
int idelayk;
REALTYPE lohifb, idelayfb, roomsize, rs; //rs is used to "normalise" the volume according to the roomsize
int comblen[REV_COMBS * 2];
int aplen[REV_APS * 2];
Unison *bandwidth;
//Internal Variables
REALTYPE *comb[REV_COMBS * 2];
int combk[REV_COMBS * 2];
REALTYPE combfb[REV_COMBS * 2]; /**<feedback-ul fiecarui filtru "comb"*/
REALTYPE lpcomb[REV_COMBS * 2]; /**<pentru Filtrul LowPass*/
REALTYPE *ap[REV_APS * 2];
int apk[REV_APS * 2];
REALTYPE *idelay;
AnalogFilter *lpf, *hpf; //filters
REALTYPE *inputbuf;
void processmono(int ch, REALTYPE *output);
};
#endif

View File

@@ -25,80 +25,88 @@
ALSAMidiIn::ALSAMidiIn()
{
int alsaport;
inputok=false;
inputok = false;
midi_handle=NULL;
midi_handle = NULL;
if (snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_INPUT,0)!=0) return;
if(snd_seq_open(&midi_handle, "default", SND_SEQ_OPEN_INPUT, 0) != 0)
return;
snd_seq_set_client_name(midi_handle,"ZynAddSubFX");//thanks to Frank Neumann
snd_seq_set_client_name(midi_handle, "ZynAddSubFX"); //thanks to Frank Neumann
alsaport = snd_seq_create_simple_port(midi_handle,"ZynAddSubFX"
,SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE
,SND_SEQ_PORT_TYPE_SYNTH);
if (alsaport<0) return;
alsaport = snd_seq_create_simple_port(
midi_handle,
"ZynAddSubFX",
SND_SEQ_PORT_CAP_WRITE
| SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_SYNTH);
if(alsaport < 0)
return;
inputok=true;
};
inputok = true;
}
ALSAMidiIn::~ALSAMidiIn()
{
if (midi_handle) snd_seq_close(midi_handle);
};
if(midi_handle)
snd_seq_close(midi_handle);
}
/*
* Get the midi command,channel and parameters
*/
void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)
void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,
unsigned char &cmdchan,
int *cmdparams)
{
snd_seq_event_t *midievent=NULL;
cmdtype=MidiNull;
snd_seq_event_t *midievent = NULL;
cmdtype = MidiNull;
if (inputok==false) {
if(inputok == false) {
/* The input is broken. We need to block for a while anyway so other
non-RT threads get a chance to run. */
sleep(1);
return;
};
}
snd_seq_event_input(midi_handle,&midievent);
snd_seq_event_input(midi_handle, &midievent);
if (midievent==NULL) return;
switch (midievent->type) {
if(midievent == NULL)
return;
switch(midievent->type) {
case SND_SEQ_EVENT_NOTEON:
cmdtype=MidiNoteON;
cmdchan=midievent->data.note.channel;
cmdparams[0]=midievent->data.note.note;
cmdparams[1]=midievent->data.note.velocity;
cmdtype = MidiNoteON;
cmdchan = midievent->data.note.channel;
cmdparams[0] = midievent->data.note.note;
cmdparams[1] = midievent->data.note.velocity;
break;
case SND_SEQ_EVENT_NOTEOFF:
cmdtype=MidiNoteOFF;
cmdchan=midievent->data.note.channel;
cmdparams[0]=midievent->data.note.note;
cmdtype = MidiNoteOFF;
cmdchan = midievent->data.note.channel;
cmdparams[0] = midievent->data.note.note;
break;
case SND_SEQ_EVENT_PITCHBEND:
cmdtype=MidiController;
cmdchan=midievent->data.control.channel;
cmdparams[0]=C_pitchwheel;//Pitch Bend
cmdparams[1]=midievent->data.control.value;
cmdtype = MidiController;
cmdchan = midievent->data.control.channel;
cmdparams[0] = C_pitchwheel; //Pitch Bend
cmdparams[1] = midievent->data.control.value;
break;
case SND_SEQ_EVENT_CONTROLLER:
cmdtype=MidiController;
cmdchan=midievent->data.control.channel;
cmdparams[0]=getcontroller(midievent->data.control.param);
cmdparams[1]=midievent->data.control.value;
cmdtype = MidiController;
cmdchan = midievent->data.control.channel;
cmdparams[0] = getcontroller(midievent->data.control.param);
cmdparams[1] = midievent->data.control.value;
//fprintf(stderr,"t=%d val=%d\n",midievent->data.control.param,midievent->data.control.value);
break;
};
};
}
}
int ALSAMidiIn::getalsaid()
{
if (midi_handle) {
snd_seq_client_info_t* seq_info;
if(midi_handle) {
snd_seq_client_info_t *seq_info;
snd_seq_client_info_malloc(&seq_info);
snd_seq_get_client_info(midi_handle, seq_info);
int id = snd_seq_client_info_get_client(seq_info);

View File

@@ -30,19 +30,21 @@
/**Midi input for ALSA (this creates an ALSA virtual port)*/
class ALSAMidiIn:public MidiIn
{
public:
/**Constructor*/
ALSAMidiIn();
/**Destructor*/
~ALSAMidiIn();
public:
/**Constructor*/
ALSAMidiIn();
/**Destructor*/
~ALSAMidiIn();
void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams);
/**Get the ALSA id
* @return ALSA id*/
int getalsaid();
void getmidicmd(MidiCmdType &cmdtype,
unsigned char &cmdchan,
int *cmdparams);
/**Get the ALSA id
* @return ALSA id*/
int getalsaid();
private:
snd_seq_t *midi_handle;
private:
snd_seq_t *midi_handle;
};
#endif

View File

@@ -26,70 +26,71 @@
int MidiIn::getcontroller(unsigned char b)
{
/**\todo there might be a better way to do this*/
int ctl=C_NULL;
switch (b) {
int ctl = C_NULL;
switch(b) {
case 1:
ctl=C_modwheel;//Modulation Wheel
ctl = C_modwheel; //Modulation Wheel
break;
case 7:
ctl=C_volume;//Volume
ctl = C_volume; //Volume
break;
case 10:
ctl=C_panning;//Panning
ctl = C_panning; //Panning
break;
case 11:
ctl=C_expression;//Expression
ctl = C_expression; //Expression
break;
case 64:
ctl=C_sustain;//Sustain pedal
ctl = C_sustain; //Sustain pedal
break;
case 65:
ctl=C_portamento;//Portamento
ctl = C_portamento; //Portamento
break;
case 71:
ctl=C_filterq;//Filter Q (Sound Timbre)
ctl = C_filterq; //Filter Q (Sound Timbre)
break;
case 74:
ctl=C_filtercutoff;//Filter Cutoff (Brightness)
ctl = C_filtercutoff; //Filter Cutoff (Brightness)
break;
case 75:
ctl=C_bandwidth;//BandWidth
ctl = C_bandwidth; //BandWidth
break;
case 76:
ctl=C_fmamp;//FM amplitude
ctl = C_fmamp; //FM amplitude
break;
case 77:
ctl=C_resonance_center;//Resonance Center Frequency
ctl = C_resonance_center; //Resonance Center Frequency
break;
case 78:
ctl=C_resonance_bandwidth;//Resonance Bandwith
ctl = C_resonance_bandwidth; //Resonance Bandwith
break;
case 120:
ctl=C_allsoundsoff;//All Sounds OFF
ctl = C_allsoundsoff; //All Sounds OFF
break;
case 121:
ctl=C_resetallcontrollers;//Reset All Controllers
ctl = C_resetallcontrollers; //Reset All Controllers
break;
case 123:
ctl=C_allnotesoff;//All Notes OFF
ctl = C_allnotesoff; //All Notes OFF
break;
//RPN and NRPN
//RPN and NRPN
case 0x06:
ctl=C_dataentryhi;//Data Entry (Coarse)
ctl = C_dataentryhi; //Data Entry (Coarse)
break;
case 0x26:
ctl=C_dataentrylo;//Data Entry (Fine)
ctl = C_dataentrylo; //Data Entry (Fine)
break;
case 99:
ctl=C_nrpnhi;//NRPN (Coarse)
ctl = C_nrpnhi; //NRPN (Coarse)
break;
case 98:
ctl=C_nrpnlo;//NRPN (Fine)
ctl = C_nrpnlo; //NRPN (Fine)
break;
default:
ctl=C_NULL;//unknown controller
ctl = C_NULL; //unknown controller
//fprintf(stderr,"Controller=%d , par=%d\n",midievent->data.control.param,cmdparams[1]);
break;
};
return(ctl);
};
}
return ctl;
}

View File

@@ -25,23 +25,27 @@
#include "../globals.h"
enum MidiCmdType {MidiNull,MidiNoteOFF,MidiNoteON,MidiController};
enum MidiCmdType {
MidiNull, MidiNoteOFF, MidiNoteON, MidiController
};
#define MP_MAX_BYTES 4000 //in case of loooong SYS_EXes
/**This class is inherited by all the Midi input classes*/
class MidiIn
{
public:
/**Get the command,channel and parameters of the MIDI
*
* \todo make pure virtual
* @param cmdtype the referece to the variable that will store the type
* @param cmdchan the channel for the event
* @param parameters for the event*/
virtual void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)=0;
int getcontroller(unsigned char b);
protected:
bool inputok;/**<1 if I can read midi bytes from input ports*/
public:
/**Get the command,channel and parameters of the MIDI
*
* \todo make pure virtual
* @param cmdtype the referece to the variable that will store the type
* @param cmdchan the channel for the event
* @param parameters for the event*/
virtual void getmidicmd(MidiCmdType &cmdtype,
unsigned char &cmdchan,
int *cmdparams) = 0;
int getcontroller(unsigned char b);
protected:
bool inputok; /**<1 if I can read midi bytes from input ports*/
};
#endif

View File

@@ -23,19 +23,19 @@
#include "NULLMidiIn.h"
NULLMidiIn::NULLMidiIn()
{
};
{}
NULLMidiIn::~NULLMidiIn()
{
};
{}
/*
* Get the midi command,channel and parameters
* It returns MidiNull because it is a dummy driver
*/
void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)
void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype,
unsigned char &cmdchan,
int *cmdparams)
{
cmdtype=MidiNull;
};
cmdtype = MidiNull;
}

View File

@@ -29,19 +29,21 @@
/**a dummy Midi port*/
class NULLMidiIn:public MidiIn
{
public:
/**Dummy Constructor
* \todo see if the default constructor would work here*/
NULLMidiIn();
/**Dummy Destructor
* \todo see if the default destructor would work here*/
~NULLMidiIn();
/**Get the midi command,channel and parameters
* It returns MidiNull because it is a dummy driver
*/
void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams);
public:
/**Dummy Constructor
* \todo see if the default constructor would work here*/
NULLMidiIn();
/**Dummy Destructor
* \todo see if the default destructor would work here*/
~NULLMidiIn();
/**Get the midi command,channel and parameters
* It returns MidiNull because it is a dummy driver
*/
void getmidicmd(MidiCmdType &cmdtype,
unsigned char &cmdchan,
int *cmdparams);
private:
private:
};
#endif

View File

@@ -33,88 +33,91 @@
OSSMidiIn::OSSMidiIn()
{
inputok=false;
midi_handle=open(config.cfg.LinuxOSSSeqInDev,O_RDONLY,0);
if (midi_handle!=-1) inputok=true;
inputok = false;
midi_handle = open(config.cfg.LinuxOSSSeqInDev, O_RDONLY, 0);
if(midi_handle != -1)
inputok = true;
lastmidicmd=0;
cmdtype=0;
cmdchan=0;
};
lastmidicmd = 0;
cmdtype = 0;
cmdchan = 0;
}
OSSMidiIn::~OSSMidiIn()
{
close(midi_handle);
};
}
unsigned char OSSMidiIn::readbyte()
{
unsigned char tmp[4];
read(midi_handle,&tmp[0],1);
while (tmp[0]!=SEQ_MIDIPUTC) {
read(midi_handle,&tmp[0],4);
read(midi_handle, &tmp[0], 1);
while(tmp[0] != SEQ_MIDIPUTC) {
read(midi_handle, &tmp[0], 4);
}
return(tmp[1]);
};
return tmp[1];
}
unsigned char OSSMidiIn::getmidibyte()
{
unsigned char b;
do {
b=readbyte();
} while (b==0xfe);//drops the Active Sense Messages
return(b);
};
b = readbyte();
} while(b == 0xfe); //drops the Active Sense Messages
return b;
}
/*
* Get the midi command,channel and parameters
*/
void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)
void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,
unsigned char &cmdchan,
int *cmdparams)
{
unsigned char tmp,i;
if (inputok==false) {
cmdtype=MidiNull;
unsigned char tmp, i;
if(inputok == false) {
cmdtype = MidiNull;
return;
}
i=0;
if (lastmidicmd==0) {//asteapta prima data pana cand vine prima comanda midi
while (tmp<0x80) tmp=getmidibyte();
lastmidicmd=tmp;
i = 0;
if(lastmidicmd == 0) { //asteapta prima data pana cand vine prima comanda midi
while(tmp < 0x80)
tmp = getmidibyte();
lastmidicmd = tmp;
}
tmp=getmidibyte();
tmp = getmidibyte();
if (tmp>=0x80) {
lastmidicmd=tmp;
tmp=getmidibyte();
if(tmp >= 0x80) {
lastmidicmd = tmp;
tmp = getmidibyte();
}
if ((lastmidicmd>=0x80)&&(lastmidicmd<=0x8f)) {//Note OFF
cmdtype=MidiNoteOFF;
cmdchan=lastmidicmd%16;
cmdparams[0]=tmp;//note number
if((lastmidicmd >= 0x80) && (lastmidicmd <= 0x8f)) { //Note OFF
cmdtype = MidiNoteOFF;
cmdchan = lastmidicmd % 16;
cmdparams[0] = tmp; //note number
}
if ((lastmidicmd>=0x90)&&(lastmidicmd<=0x9f)) {//Note ON
cmdtype=MidiNoteON;
cmdchan=lastmidicmd%16;
cmdparams[0]=tmp;//note number
cmdparams[1]=getmidibyte();//velocity
if (cmdparams[1]==0) cmdtype=MidiNoteOFF;//if velocity==0 then is note off
if((lastmidicmd >= 0x90) && (lastmidicmd <= 0x9f)) { //Note ON
cmdtype = MidiNoteON;
cmdchan = lastmidicmd % 16;
cmdparams[0] = tmp; //note number
cmdparams[1] = getmidibyte(); //velocity
if(cmdparams[1] == 0)
cmdtype = MidiNoteOFF; //if velocity==0 then is note off
}
if ((lastmidicmd>=0xB0)&&(lastmidicmd<=0xBF)) {//Controllers
cmdtype=MidiController;
cmdchan=lastmidicmd%16;
cmdparams[0]=getcontroller(tmp);
cmdparams[1]=getmidibyte();
if((lastmidicmd >= 0xB0) && (lastmidicmd <= 0xBF)) { //Controllers
cmdtype = MidiController;
cmdchan = lastmidicmd % 16;
cmdparams[0] = getcontroller(tmp);
cmdparams[1] = getmidibyte();
}
if ((lastmidicmd>=0xE0)&&(lastmidicmd<=0xEF)) {//Pitch Wheel
cmdtype=MidiController;
cmdchan=lastmidicmd%16;
cmdparams[0]=C_pitchwheel;
cmdparams[1]=(tmp+getmidibyte()*(int) 128)-8192;//hope this is correct
if((lastmidicmd >= 0xE0) && (lastmidicmd <= 0xEF)) { //Pitch Wheel
cmdtype = MidiController;
cmdchan = lastmidicmd % 16;
cmdparams[0] = C_pitchwheel;
cmdparams[1] = (tmp + getmidibyte() * (int) 128) - 8192; //hope this is correct
}
};
}

View File

@@ -27,21 +27,22 @@
class OSSMidiIn:public MidiIn
{
public:
OSSMidiIn();
~OSSMidiIn();
unsigned char getmidibyte();
unsigned char readbyte();
public:
OSSMidiIn();
~OSSMidiIn();
unsigned char getmidibyte();
unsigned char readbyte();
//Midi parser
void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams);
unsigned char cmdtype;//the Message Type (noteon,noteof,sysex..)
unsigned char cmdchan;//the channel number
private:
int midi_handle;
unsigned char lastmidicmd;//last byte (>=80) received from the Midi
//Midi parser
void getmidicmd(MidiCmdType &cmdtype,
unsigned char &cmdchan,
int *cmdparams);
unsigned char cmdtype; //the Message Type (noteon,noteof,sysex..)
unsigned char cmdchan; //the channel number
private:
int midi_handle;
unsigned char lastmidicmd; //last byte (>=80) received from the Midi
};

View File

@@ -32,56 +32,63 @@
Master *winmaster;
HMIDIIN winmidiinhandle;
MidiIn midictl;//used to convert the controllers to ZynAddSubFX controllers
MidiIn midictl; //used to convert the controllers to ZynAddSubFX controllers
void CALLBACK WinMidiInProc(HMIDIIN hMidiIn,UINT wMsg,DWORD dwInstance,
DWORD dwParam1,DWORD dwParam2)
void CALLBACK WinMidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2)
{
int midicommand=MidiNull;
if (wMsg==MIM_DATA) {
int cmd,par1,par2;
cmd=dwParam1&0xff;
if (cmd==0xfe) return;
par1=(dwParam1>>8)&0xff;
par2=dwParam1>>16;
int midicommand = MidiNull;
if(wMsg == MIM_DATA) {
int cmd, par1, par2;
cmd = dwParam1 & 0xff;
if(cmd == 0xfe)
return;
par1 = (dwParam1 >> 8) & 0xff;
par2 = dwParam1 >> 16;
//printf("%x %x %x\n",cmd,par1,par2);fflush(stdout);
int cmdchan=cmd&0x0f;
int cmdtype=(cmd>>4)&0x0f;
int cmdchan = cmd & 0x0f;
int cmdtype = (cmd >> 4) & 0x0f;
int tmp=0;
int tmp = 0;
pthread_mutex_lock(&winmaster->mutex);
switch (cmdtype) {
case(0x8)://noteon
winmaster->NoteOff(cmdchan,par1);
switch(cmdtype) {
case (0x8): //noteon
winmaster->NoteOff(cmdchan, par1);
break;
case(0x9)://noteoff
winmaster->NoteOn(cmdchan,par1,par2&0xff);
case (0x9): //noteoff
winmaster->NoteOn(cmdchan, par1, par2 & 0xff);
break;
case(0xb)://controller
winmaster->SetController(cmdchan,midictl.getcontroller(par1),par2&0xff);
case (0xb): //controller
winmaster->SetController(cmdchan, midictl.getcontroller(
par1), par2 & 0xff);
break;
case(0xe)://pitch wheel
tmp=(par1+par2*(long int) 128)-8192;
winmaster->SetController(cmdchan,C_pitchwheel,tmp);
case (0xe): //pitch wheel
tmp = (par1 + par2 * (long int) 128) - 8192;
winmaster->SetController(cmdchan, C_pitchwheel, tmp);
break;
default:
break;
};
}
pthread_mutex_unlock(&winmaster->mutex);
};
};
}
}
void InitWinMidi(Master *master_)
{
winmaster=master_;
winmaster = master_;
long int result=midiInOpen(&winmidiinhandle,config.cfg.WindowsMidiInId,(DWORD)WinMidiInProc,0,CALLBACK_FUNCTION);
result=midiInStart(winmidiinhandle);
};
long int result =
midiInOpen(&winmidiinhandle,
config.cfg.WindowsMidiInId,
(DWORD)WinMidiInProc,
0,
CALLBACK_FUNCTION);
result = midiInStart(winmidiinhandle);
}
void StopWinMidi()
{
midiInStop(winmidiinhandle);
midiInClose(winmidiinhandle);
};
}

View File

@@ -41,183 +41,213 @@
Bank::Bank()
{
ZERO(defaultinsname, PART_MAX_NAME_LEN);
snprintf(defaultinsname, PART_MAX_NAME_LEN, "%s", " ");
ZERO(defaultinsname,PART_MAX_NAME_LEN);
snprintf(defaultinsname,PART_MAX_NAME_LEN,"%s"," ");
for (int i=0;i<BANK_SIZE;i++) {
ins[i].used=false;
ins[i].filename=NULL;
ins[i].info.PADsynth_used=false;
};
dirname=NULL;
for(int i = 0; i < BANK_SIZE; i++) {
ins[i].used = false;
ins[i].filename = NULL;
ins[i].info.PADsynth_used = false;
}
dirname = NULL;
clearbank();
for (int i=0;i<MAX_NUM_BANKS;i++) {
banks[i].dir=NULL;
banks[i].name=NULL;
};
for(int i = 0; i < MAX_NUM_BANKS; i++) {
banks[i].dir = NULL;
banks[i].name = NULL;
}
bankfiletitle=dirname;
bankfiletitle = dirname;
loadbank(config.cfg.currentBankDir);
};
}
Bank::~Bank()
{
for (int i=0;i<MAX_NUM_BANKS;i++) {
if (banks[i].dir!=NULL) delete []banks[i].dir;
if (banks[i].name!=NULL) delete []banks[i].name;
};
for(int i = 0; i < MAX_NUM_BANKS; i++) {
if(banks[i].dir != NULL)
delete [] banks[i].dir;
if(banks[i].name != NULL)
delete [] banks[i].name;
}
clearbank();
};
}
/*
* Get the name of an instrument from the bank
*/
char *Bank::getname (unsigned int ninstrument)
char *Bank::getname(unsigned int ninstrument)
{
if (emptyslot(ninstrument)) return (defaultinsname);
return (ins[ninstrument].name);
};
if(emptyslot(ninstrument))
return defaultinsname;
return ins[ninstrument].name;
}
/*
* Get the numbered name of an instrument from the bank
*/
char *Bank::getnamenumbered (unsigned int ninstrument)
char *Bank::getnamenumbered(unsigned int ninstrument)
{
if (emptyslot(ninstrument)) return (defaultinsname);
snprintf(tmpinsname[ninstrument],PART_MAX_NAME_LEN+15,"%d. %s",ninstrument+1,getname(ninstrument));
return(tmpinsname[ninstrument]);
};
if(emptyslot(ninstrument))
return defaultinsname;
snprintf(tmpinsname[ninstrument],
PART_MAX_NAME_LEN + 15,
"%d. %s",
ninstrument + 1,
getname(ninstrument));
return tmpinsname[ninstrument];
}
/*
* Changes the name of an instrument (and the filename)
*/
void Bank::setname(unsigned int ninstrument,const char *newname,int newslot)
void Bank::setname(unsigned int ninstrument, const char *newname, int newslot)
{
if (emptyslot(ninstrument)) return;
if(emptyslot(ninstrument))
return;
char newfilename[1000+1],tmpfilename[100+1];
char newfilename[1000 + 1], tmpfilename[100 + 1];
ZERO(newfilename,1001);
ZERO(tmpfilename,101);
if (newslot>=0) snprintf(tmpfilename,100,"%4d-%s",newslot+1,newname);
else snprintf(tmpfilename,100,"%4d-%s",ninstrument+1,newname);
ZERO(newfilename, 1001);
ZERO(tmpfilename, 101);
if(newslot >= 0)
snprintf(tmpfilename, 100, "%4d-%s", newslot + 1, newname);
else
snprintf(tmpfilename, 100, "%4d-%s", ninstrument + 1, newname);
//add the zeroes at the start of filename
for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0';
for(int i = 0; i < 4; i++)
if(tmpfilename[i] == ' ')
tmpfilename[i] = '0';
//make the filenames legal
for (int i=0;i<(int) strlen(tmpfilename);i++) {
char c=tmpfilename[i];
if ((c>='0')&&(c<='9')) continue;
if ((c>='A')&&(c<='Z')) continue;
if ((c>='a')&&(c<='z')) continue;
if ((c=='-')||(c==' ')) continue;
for(int i = 0; i < (int) strlen(tmpfilename); i++) {
char c = tmpfilename[i];
if((c >= '0') && (c <= '9'))
continue;
if((c >= 'A') && (c <= 'Z'))
continue;
if((c >= 'a') && (c <= 'z'))
continue;
if((c == '-') || (c == ' '))
continue;
tmpfilename[i]='_';
};
tmpfilename[i] = '_';
}
snprintf(newfilename,1000,"%s/%s.xiz",dirname,tmpfilename);
snprintf(newfilename, 1000, "%s/%s.xiz", dirname, tmpfilename);
// printf("rename %s -> %s\n",ins[ninstrument].filename,newfilename);//////////////
rename(ins[ninstrument].filename,newfilename);
if (ins[ninstrument].filename) delete []ins[ninstrument].filename;
ins[ninstrument].filename=new char[strlen(newfilename)+5];
snprintf(ins[ninstrument].filename,strlen(newfilename)+1,"%s",newfilename);
snprintf(ins[ninstrument].name,PART_MAX_NAME_LEN,"%s",&tmpfilename[5]);
};
rename(ins[ninstrument].filename, newfilename);
if(ins[ninstrument].filename)
delete [] ins[ninstrument].filename;
ins[ninstrument].filename = new char[strlen(newfilename) + 5];
snprintf(ins[ninstrument].filename, strlen(
newfilename) + 1, "%s", newfilename);
snprintf(ins[ninstrument].name, PART_MAX_NAME_LEN, "%s", &tmpfilename[5]);
}
/*
* Check if there is no instrument on a slot from the bank
*/
int Bank::emptyslot(unsigned int ninstrument)
{
if (ninstrument>=BANK_SIZE) return (1);
if (ins[ninstrument].filename==NULL) return(1);
if(ninstrument >= BANK_SIZE)
return 1;
if(ins[ninstrument].filename == NULL)
return 1;
if (ins[ninstrument].used) return (0);
else return(1);
};
if(ins[ninstrument].used)
return 0;
else
return 1;
}
/*
* Removes the instrument from the bank
*/
void Bank::clearslot(unsigned int ninstrument)
{
if (emptyslot(ninstrument)) return;
if(emptyslot(ninstrument))
return;
// printf("remove %s \n",ins[ninstrument].filename);////////////////////////
remove(ins[ninstrument].filename);
deletefrombank(ninstrument);
};
}
/*
* Save the instrument to a slot
*/
void Bank::savetoslot(unsigned int ninstrument,Part *part)
void Bank::savetoslot(unsigned int ninstrument, Part *part)
{
clearslot(ninstrument);
const int maxfilename=200;
char tmpfilename[maxfilename+20];
ZERO(tmpfilename,maxfilename+20);
const int maxfilename = 200;
char tmpfilename[maxfilename + 20];
ZERO(tmpfilename, maxfilename + 20);
snprintf(tmpfilename,maxfilename,"%4d-%s",ninstrument+1,(char *)part->Pname);
snprintf(tmpfilename,
maxfilename,
"%4d-%s",
ninstrument + 1,
(char *)part->Pname);
//add the zeroes at the start of filename
for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0';
for(int i = 0; i < 4; i++)
if(tmpfilename[i] == ' ')
tmpfilename[i] = '0';
//make the filenames legal
for (int i=0;i<(int)strlen(tmpfilename);i++) {
char c=tmpfilename[i];
if ((c>='0')&&(c<='9')) continue;
if ((c>='A')&&(c<='Z')) continue;
if ((c>='a')&&(c<='z')) continue;
if ((c=='-')||(c==' ')) continue;
for(int i = 0; i < (int)strlen(tmpfilename); i++) {
char c = tmpfilename[i];
if((c >= '0') && (c <= '9'))
continue;
if((c >= 'A') && (c <= 'Z'))
continue;
if((c >= 'a') && (c <= 'z'))
continue;
if((c == '-') || (c == ' '))
continue;
tmpfilename[i]='_';
};
tmpfilename[i] = '_';
}
strncat(tmpfilename,".xiz",maxfilename+10);
strncat(tmpfilename, ".xiz", maxfilename + 10);
int fnsize=strlen(dirname)+strlen(tmpfilename)+10;
char *filename=new char[fnsize+4];
ZERO(filename,fnsize+2);
int fnsize = strlen(dirname) + strlen(tmpfilename) + 10;
char *filename = new char[fnsize + 4];
ZERO(filename, fnsize + 2);
snprintf(filename,fnsize,"%s/%s",dirname,tmpfilename);
snprintf(filename, fnsize, "%s/%s", dirname, tmpfilename);
remove(filename);
part->saveXML(filename);
addtobank(ninstrument,tmpfilename,(char *) part->Pname);
addtobank(ninstrument, tmpfilename, (char *) part->Pname);
delete[]filename;
};
delete[] filename;
}
/*
* Loads the instrument from the bank
*/
void Bank::loadfromslot(unsigned int ninstrument,Part *part)
void Bank::loadfromslot(unsigned int ninstrument, Part *part)
{
if (emptyslot(ninstrument)) return;
if(emptyslot(ninstrument))
return;
part->defaultsinstrument();
// printf("load: %s\n",ins[ninstrument].filename);
part->loadXMLinstrument(ins[ninstrument].filename);
};
}
/*
@@ -225,160 +255,173 @@ void Bank::loadfromslot(unsigned int ninstrument,Part *part)
*/
int Bank::loadbank(const char *bankdirname)
{
DIR *dir=opendir(bankdirname);
DIR *dir = opendir(bankdirname);
clearbank();
if (dir==NULL) return(-1);
if(dir == NULL)
return -1;
if (dirname!=NULL) delete[]dirname;
dirname=new char[strlen(bankdirname)+1];
snprintf(dirname,strlen(bankdirname)+1,"%s",bankdirname);
if(dirname != NULL)
delete[] dirname;
dirname = new char[strlen(bankdirname) + 1];
snprintf(dirname, strlen(bankdirname) + 1, "%s", bankdirname);
bankfiletitle=dirname;
bankfiletitle = dirname;
// printf("loadbank %s/\n",bankdirname);
struct dirent *fn;
while ((fn=readdir(dir))) {
const char *filename= fn->d_name;
while((fn = readdir(dir))) {
const char *filename = fn->d_name;
//sa verific daca e si extensia dorita
if (strstr(filename,INSTRUMENT_EXTENSION)==NULL) continue;
if(strstr(filename, INSTRUMENT_EXTENSION) == NULL)
continue;
//verify if the name is like this NNNN-name (where N is a digit)
int no=0;
unsigned int startname=0;
int no = 0;
unsigned int startname = 0;
for (unsigned int i=0;i<4;i++) {
if (strlen(filename)<=i) break;
for(unsigned int i = 0; i < 4; i++) {
if(strlen(filename) <= i)
break;
if ((filename[i]>='0')&&(filename[i]<='9')) {
no=no*10+(filename[i]-'0');
if((filename[i] >= '0') && (filename[i] <= '9')) {
no = no * 10 + (filename[i] - '0');
startname++;
};
};
}
}
if ((startname+1)<strlen(filename)) startname++;//to take out the "-"
if((startname + 1) < strlen(filename))
startname++; //to take out the "-"
char name[PART_MAX_NAME_LEN+1];
ZERO(name,PART_MAX_NAME_LEN+1);
snprintf(name,PART_MAX_NAME_LEN,"%s",filename);
char name[PART_MAX_NAME_LEN + 1];
ZERO(name, PART_MAX_NAME_LEN + 1);
snprintf(name, PART_MAX_NAME_LEN, "%s", filename);
//remove the file extension
for (int i=strlen(name)-1;i>=2;i--) {
if (name[i]=='.') {
name[i]='\0';
for(int i = strlen(name) - 1; i >= 2; i--) {
if(name[i] == '.') {
name[i] = '\0';
break;
};
};
}
}
if (no!=0) {//the instrument position in the bank is found
addtobank(no-1,filename,&name[startname]);
} else {
addtobank(-1,filename,name);
};
};
if(no != 0) //the instrument position in the bank is found
addtobank(no - 1, filename, &name[startname]);
else
addtobank(-1, filename, name);
;
}
closedir(dir);
if (dirname!=NULL) {
sprintf(config.cfg.currentBankDir,"%s",dirname);
};
if(dirname != NULL)
sprintf(config.cfg.currentBankDir, "%s", dirname);
;
return(0);
};
return 0;
}
/*
* Makes a new bank, put it on a file and makes it current bank
*/
int Bank::newbank(const char *newbankdirname)
{
int result;
int result;
char tmpfilename[MAX_STRING_SIZE];
char bankdir[MAX_STRING_SIZE];
snprintf(bankdir,MAX_STRING_SIZE,"%s",config.cfg.bankRootDirList[0]);
snprintf(bankdir, MAX_STRING_SIZE, "%s", config.cfg.bankRootDirList[0]);
if (((bankdir[strlen(bankdir)-1])!='/')&&((bankdir[strlen(bankdir)-1])!='\\')) {
strncat(bankdir,"/",MAX_STRING_SIZE);
};
strncat(bankdir,newbankdirname,MAX_STRING_SIZE);
if(((bankdir[strlen(bankdir) - 1]) != '/')
&& ((bankdir[strlen(bankdir) - 1]) != '\\'))
strncat(bankdir, "/", MAX_STRING_SIZE);
;
strncat(bankdir, newbankdirname, MAX_STRING_SIZE);
#ifdef OS_WINDOWS
result=mkdir(bankdir);
result = mkdir(bankdir);
#else
result=mkdir(bankdir,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
result = mkdir(bankdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
if (result<0) return(-1);
if(result < 0)
return -1;
snprintf(tmpfilename,MAX_STRING_SIZE,"%s/%s",bankdir,FORCE_BANK_DIR_FILE);
snprintf(tmpfilename,
MAX_STRING_SIZE,
"%s/%s",
bankdir,
FORCE_BANK_DIR_FILE);
// printf("%s\n",tmpfilename);
FILE *tmpfile=fopen(tmpfilename,"w+");
FILE *tmpfile = fopen(tmpfilename, "w+");
fclose(tmpfile);
return(loadbank(bankdir));
};
return loadbank(bankdir);
}
/*
* Check if the bank is locked (i.e. the file opened was readonly)
*/
int Bank::locked()
{
return(dirname==NULL);
};
return dirname == NULL;
}
/*
* Swaps a slot with another
*/
void Bank::swapslot(unsigned int n1, unsigned int n2)
{
if ((n1==n2)||(locked())) return;
if (emptyslot(n1)&&(emptyslot(n2))) return;
if (emptyslot(n1)) {//change n1 to n2 in order to make
int tmp=n2;
n2=n1;
n1=tmp;
};
if((n1 == n2) || (locked()))
return;
if(emptyslot(n1) && (emptyslot(n2)))
return;
if(emptyslot(n1)) { //change n1 to n2 in order to make
int tmp = n2;
n2 = n1;
n1 = tmp;
}
if (emptyslot(n2)) {//this is just a movement from slot1 to slot2
setname(n1,getname(n1),n2);
ins[n2]=ins[n1];
ins[n1].used=false;
ins[n1].name[0]='\0';
ins[n1].filename=NULL;
ins[n1].info.PADsynth_used=0;
} else {//if both slots are used
if (strcmp(ins[n1].name,ins[n2].name)==0) {//change the name of the second instrument if the name are equal
strncat(ins[n2].name,"2",PART_MAX_NAME_LEN);
};
setname(n1,getname(n1),n2);
setname(n2,getname(n2),n1);
if(emptyslot(n2)) { //this is just a movement from slot1 to slot2
setname(n1, getname(n1), n2);
ins[n2] = ins[n1];
ins[n1].used = false;
ins[n1].name[0] = '\0';
ins[n1].filename = NULL;
ins[n1].info.PADsynth_used = 0;
}
else { //if both slots are used
if(strcmp(ins[n1].name, ins[n2].name) == 0) //change the name of the second instrument if the name are equal
strncat(ins[n2].name, "2", PART_MAX_NAME_LEN);
;
setname(n1, getname(n1), n2);
setname(n2, getname(n2), n1);
ins_t tmp;
tmp.used=true;
strcpy(tmp.name,ins[n2].name);
char *tmpfilename=ins[n2].filename;
bool padsynth_used=ins[n2].info.PADsynth_used;
tmp.used = true;
strcpy(tmp.name, ins[n2].name);
char *tmpfilename = ins[n2].filename;
bool padsynth_used = ins[n2].info.PADsynth_used;
ins[n2]=ins[n1];
strcpy(ins[n1].name,tmp.name);
ins[n1].filename=tmpfilename;
ins[n1].info.PADsynth_used=padsynth_used;
};
};
ins[n2] = ins[n1];
strcpy(ins[n1].name, tmp.name);
ins[n1].filename = tmpfilename;
ins[n1].info.PADsynth_used = padsynth_used;
}
}
//a helper function that compares 2 banks[] arrays
int Bank_compar(const void *a,const void *b)
int Bank_compar(const void *a, const void *b)
{
struct Bank::bankstruct *bank1= (Bank::bankstruct *)a;
struct Bank::bankstruct *bank2= (Bank::bankstruct *)b;
if (((bank1->name)==NULL)||((bank2->name)==NULL)) return(0);
struct Bank::bankstruct *bank1 = (Bank::bankstruct *)a;
struct Bank::bankstruct *bank2 = (Bank::bankstruct *)b;
if(((bank1->name) == NULL) || ((bank2->name) == NULL))
return 0;
int result=strcasecmp(bank1->name,bank2->name);
return(result<0);
};
int result = strcasecmp(bank1->name, bank2->name);
return result < 0;
}
/*
@@ -387,56 +430,61 @@ int Bank_compar(const void *a,const void *b)
void Bank::rescanforbanks()
{
for (int i=0;i<MAX_NUM_BANKS;i++) {
if (banks[i].dir!=NULL) delete []banks[i].dir;
if (banks[i].name!=NULL) delete []banks[i].name;
banks[i].dir=NULL;
banks[i].name=NULL;
};
for(int i = 0; i < MAX_NUM_BANKS; i++) {
if(banks[i].dir != NULL)
delete [] banks[i].dir;
if(banks[i].name != NULL)
delete [] banks[i].name;
banks[i].dir = NULL;
banks[i].name = NULL;
}
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (config.cfg.bankRootDirList[i]!=NULL) scanrootdir(config.cfg.bankRootDirList[i]);
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
if(config.cfg.bankRootDirList[i] != NULL)
scanrootdir(config.cfg.bankRootDirList[i]);
//sort the banks
for (int j=0;j<MAX_NUM_BANKS-1;j++) {
for (int i=j+1;i<MAX_NUM_BANKS;i++) {
if (Bank_compar(&banks[i],&banks[j])) {
char *tmpname=banks[i].name;
char *tmpdir=banks[i].dir;
for(int j = 0; j < MAX_NUM_BANKS - 1; j++) {
for(int i = j + 1; i < MAX_NUM_BANKS; i++) {
if(Bank_compar(&banks[i], &banks[j])) {
char *tmpname = banks[i].name;
char *tmpdir = banks[i].dir;
banks[i].name=banks[j].name;
banks[i].dir=banks[j].dir;
banks[i].name = banks[j].name;
banks[i].dir = banks[j].dir;
banks[j].name=tmpname;
banks[j].dir=tmpdir;
};
};
};
banks[j].name = tmpname;
banks[j].dir = tmpdir;
}
}
}
//remove duplicate bank names
int dupl=0;
for (int j=0;j<MAX_NUM_BANKS-1;j++) {
for (int i=j+1;i<MAX_NUM_BANKS;i++) {
if ((banks[i].name==NULL)||(banks[j].name==NULL)) continue;
if (strcmp(banks[i].name,banks[j].name)==0) {//add a [1] to the first bankname and [n] to others
char *tmpname=banks[i].name;
banks[i].name=new char[strlen(tmpname)+100];
sprintf(banks[i].name,"%s[%d]",tmpname,dupl+2);
delete[]tmpname;
int dupl = 0;
for(int j = 0; j < MAX_NUM_BANKS - 1; j++) {
for(int i = j + 1; i < MAX_NUM_BANKS; i++) {
if((banks[i].name == NULL) || (banks[j].name == NULL))
continue;
if(strcmp(banks[i].name, banks[j].name) == 0) { //add a [1] to the first bankname and [n] to others
char *tmpname = banks[i].name;
banks[i].name = new char[strlen(tmpname) + 100];
sprintf(banks[i].name, "%s[%d]", tmpname, dupl + 2);
delete[] tmpname;
if (dupl==0) {
char *tmpname=banks[j].name;
banks[j].name=new char[strlen(tmpname)+100];
sprintf(banks[j].name,"%s[1]",tmpname);
delete[]tmpname;
};
if(dupl == 0) {
char *tmpname = banks[j].name;
banks[j].name = new char[strlen(tmpname) + 100];
sprintf(banks[j].name, "%s[1]", tmpname);
delete[] tmpname;
}
dupl++;
} else dupl=0;
};
};
};
}
else
dupl = 0;
}
}
}
@@ -445,140 +493,152 @@ void Bank::rescanforbanks()
void Bank::scanrootdir(char *rootdir)
{
// printf("Scanning root dir:%s\n",rootdir);
DIR *dir=opendir(rootdir);
if (dir==NULL) return;
DIR *dir = opendir(rootdir);
if(dir == NULL)
return;
const int maxdirsize=1000;
const int maxdirsize = 1000;
struct {
char dir[maxdirsize];
char name[maxdirsize];
}bank;
} bank;
const char *separator="/";
if (strlen(rootdir)) {
char tmp=rootdir[strlen(rootdir)-1];
if ((tmp=='/') || (tmp=='\\')) separator="";
};
const char *separator = "/";
if(strlen(rootdir)) {
char tmp = rootdir[strlen(rootdir) - 1];
if((tmp == '/') || (tmp == '\\'))
separator = "";
}
struct dirent *fn;
while ((fn=readdir(dir))) {
const char *dirname=fn->d_name;
if (dirname[0]=='.') continue;
while((fn = readdir(dir))) {
const char *dirname = fn->d_name;
if(dirname[0] == '.')
continue;
snprintf(bank.dir,maxdirsize,"%s%s%s/",rootdir,separator,dirname);
snprintf(bank.name,maxdirsize,"%s",dirname);
snprintf(bank.dir, maxdirsize, "%s%s%s/", rootdir, separator, dirname);
snprintf(bank.name, maxdirsize, "%s", dirname);
//find out if the directory contains at least 1 instrument
bool isbank=false;
bool isbank = false;
DIR *d=opendir(bank.dir);
if (d==NULL) continue;
DIR *d = opendir(bank.dir);
if(d == NULL)
continue;
struct dirent *fname;
while ((fname=readdir(d))) {
if ((strstr(fname->d_name,INSTRUMENT_EXTENSION)!=NULL)||
(strstr(fname->d_name,FORCE_BANK_DIR_FILE)!=NULL)) {
isbank=true;
break;//aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank
};
};
while((fname = readdir(d))) {
if((strstr(fname->d_name, INSTRUMENT_EXTENSION) != NULL)
|| (strstr(fname->d_name, FORCE_BANK_DIR_FILE) != NULL)) {
isbank = true;
break; //aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank
}
}
closedir(d);
if (isbank) {
int pos=-1;
for (int i=1;i<MAX_NUM_BANKS;i++) { //banks[0] e liber intotdeauna
if (banks[i].name==NULL) {
pos=i;
if(isbank) {
int pos = -1;
for(int i = 1; i < MAX_NUM_BANKS; i++) { //banks[0] e liber intotdeauna
if(banks[i].name == NULL) {
pos = i;
break;
};
};
}
}
if (pos>=0) {
banks[pos].name=new char[maxdirsize];
banks[pos].dir=new char[maxdirsize];
snprintf(banks[pos].name,maxdirsize,"%s",bank.name);
snprintf(banks[pos].dir,maxdirsize,"%s",bank.dir);
};
};
};
if(pos >= 0) {
banks[pos].name = new char[maxdirsize];
banks[pos].dir = new char[maxdirsize];
snprintf(banks[pos].name, maxdirsize, "%s", bank.name);
snprintf(banks[pos].dir, maxdirsize, "%s", bank.dir);
}
}
}
closedir(dir);
};
}
void Bank::clearbank()
{
for (int i=0;i<BANK_SIZE;i++) deletefrombank(i);
if (dirname!=NULL) delete[]dirname;
bankfiletitle=NULL;
dirname=NULL;
};
for(int i = 0; i < BANK_SIZE; i++)
deletefrombank(i);
if(dirname != NULL)
delete[] dirname;
bankfiletitle = NULL;
dirname = NULL;
}
int Bank::addtobank(int pos, const char *filename, const char* name)
int Bank::addtobank(int pos, const char *filename, const char *name)
{
if ((pos>=0)&&(pos<BANK_SIZE)) {
if (ins[pos].used) pos=-1;//force it to find a new free position
} else if (pos>=BANK_SIZE) pos=-1;
if((pos >= 0) && (pos < BANK_SIZE)) {
if(ins[pos].used)
pos = -1; //force it to find a new free position
}
else
if(pos >= BANK_SIZE)
pos = -1;
if (pos<0) {//find a free position
for (int i=BANK_SIZE-1;i>=0;i--)
if (!ins[i].used) {
pos=i;
if(pos < 0) { //find a free position
for(int i = BANK_SIZE - 1; i >= 0; i--)
if(!ins[i].used) {
pos = i;
break;
};
}
;
}
};
if (pos<0) return (-1);//the bank is full
if(pos < 0)
return -1; //the bank is full
// printf("%s %d\n",filename,pos);
deletefrombank(pos);
ins[pos].used=true;
snprintf(ins[pos].name,PART_MAX_NAME_LEN,"%s",name);
ins[pos].used = true;
snprintf(ins[pos].name, PART_MAX_NAME_LEN, "%s", name);
snprintf(tmpinsname[pos],PART_MAX_NAME_LEN+10," ");
snprintf(tmpinsname[pos], PART_MAX_NAME_LEN + 10, " ");
int len=strlen(filename)+1+strlen(dirname);
ins[pos].filename=new char[len+2];
ins[pos].filename[len+1]=0;
snprintf(ins[pos].filename,len+1,"%s/%s",dirname,filename);
int len = strlen(filename) + 1 + strlen(dirname);
ins[pos].filename = new char[len + 2];
ins[pos].filename[len + 1] = 0;
snprintf(ins[pos].filename, len + 1, "%s/%s", dirname, filename);
//see if PADsynth is used
if (config.cfg.CheckPADsynth) {
XMLwrapper *xml=new XMLwrapper();
xml->checkfileinformation(ins[pos].filename);
if(config.cfg.CheckPADsynth) {
XMLwrapper *xml = new XMLwrapper();
xml->loadXMLfile(ins[pos].filename);
ins[pos].info.PADsynth_used=xml->information.PADsynth_used;
ins[pos].info.PADsynth_used = xml->hasPadSynth();
delete xml;
} else ins[pos].info.PADsynth_used=false;
}
else
ins[pos].info.PADsynth_used = false;
return(0);
};
return 0;
}
bool Bank::isPADsynth_used(unsigned int ninstrument)
{
if (config.cfg.CheckPADsynth==0) return(0);
else return(ins[ninstrument].info.PADsynth_used);
};
if(config.cfg.CheckPADsynth == 0)
return 0;
else
return ins[ninstrument].info.PADsynth_used;
}
void Bank::deletefrombank(int pos)
{
if ((pos<0)||(pos>=BANK_SIZE)) return;
ins[pos].used=false;
ZERO(ins[pos].name,PART_MAX_NAME_LEN+1);
if (ins[pos].filename!=NULL) {
delete []ins[pos].filename;
ins[pos].filename=NULL;
};
if((pos < 0) || (pos >= BANK_SIZE))
return;
ins[pos].used = false;
ZERO(ins[pos].name, PART_MAX_NAME_LEN + 1);
if(ins[pos].filename != NULL) {
delete [] ins[pos].filename;
ins[pos].filename = NULL;
}
ZERO(tmpinsname[pos],PART_MAX_NAME_LEN+20);
};
ZERO(tmpinsname[pos], PART_MAX_NAME_LEN + 20);
}

View File

@@ -38,70 +38,70 @@
* \todo add in strings to replace char* */
class Bank
{
public:
/**Constructor*/
Bank();
~Bank();
char *getname(unsigned int ninstrument);
char *getnamenumbered(unsigned int ninstrument);
void setname(unsigned int ninstrument,const char *newname,int newslot);//if newslot==-1 then this is ignored, else it will be put on that slot
bool isPADsynth_used(unsigned int ninstrument);
public:
/**Constructor*/
Bank();
~Bank();
char *getname(unsigned int ninstrument);
char *getnamenumbered(unsigned int ninstrument);
void setname(unsigned int ninstrument, const char *newname, int newslot); //if newslot==-1 then this is ignored, else it will be put on that slot
bool isPADsynth_used(unsigned int ninstrument);
/**returns 0 if the slot is not empty or 1 if the slot is empty
* \todo start using bool before facepalm*/
int emptyslot(unsigned int ninstrument);
/**returns 0 if the slot is not empty or 1 if the slot is empty
* \todo start using bool before facepalm*/
int emptyslot(unsigned int ninstrument);
/**Empties out the selected slot*/
void clearslot(unsigned int ninstrument);
/**Saves the given Part to slot*/
void savetoslot(unsigned int ninstrument,Part *part);
/**Loads the given slot into a Part*/
void loadfromslot(unsigned int ninstrument,Part *part);
/**Empties out the selected slot*/
void clearslot(unsigned int ninstrument);
/**Saves the given Part to slot*/
void savetoslot(unsigned int ninstrument, Part *part);
/**Loads the given slot into a Part*/
void loadfromslot(unsigned int ninstrument, Part *part);
/**Swaps Slots*/
void swapslot(unsigned int n1,unsigned int n2);
/**Swaps Slots*/
void swapslot(unsigned int n1, unsigned int n2);
int loadbank(const char *bankdirname);
int newbank(const char *newbankdirname);
int loadbank(const char *bankdirname);
int newbank(const char *newbankdirname);
char *bankfiletitle; //this is shown on the UI of the bank (the title of the window)
int locked();
char *bankfiletitle; //this is shown on the UI of the bank (the title of the window)
int locked();
void rescanforbanks();
void rescanforbanks();
struct bankstruct {
char *dir;
char *name;
};
struct bankstruct {
char *dir;
char *name;
};
bankstruct banks[MAX_NUM_BANKS];
bankstruct banks[MAX_NUM_BANKS];
private:
private:
//it adds a filename to the bank
//if pos is -1 it try to find a position
//returns -1 if the bank is full, or 0 if the instrument was added
int addtobank(int pos,const char* filename,const char* name);
//it adds a filename to the bank
//if pos is -1 it try to find a position
//returns -1 if the bank is full, or 0 if the instrument was added
int addtobank(int pos, const char *filename, const char *name);
void deletefrombank(int pos);
void deletefrombank(int pos);
void clearbank();
void clearbank();
char defaultinsname[PART_MAX_NAME_LEN];
char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN+20];//this keeps the numbered names
char defaultinsname[PART_MAX_NAME_LEN];
char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN + 20]; //this keeps the numbered names
struct ins_t {
bool used;
char name[PART_MAX_NAME_LEN+1];
char *filename;
struct {
bool PADsynth_used;
} info;
}ins[BANK_SIZE];
struct ins_t {
bool used;
char name[PART_MAX_NAME_LEN + 1];
char *filename;
struct {
bool PADsynth_used;
} info;
} ins[BANK_SIZE];
char *dirname;
char *dirname;
void scanrootdir(char *rootdir);//scans a root dir for banks
void scanrootdir(char *rootdir); //scans a root dir for banks
};
#endif

View File

@@ -33,309 +33,369 @@
#include "XMLwrapper.h"
Config::Config()
{
};
{}
void Config::init()
{
maxstringsize=MAX_STRING_SIZE;//for ui
maxstringsize = MAX_STRING_SIZE; //for ui
//defaults
cfg.SampleRate=44100;
cfg.SoundBufferSize=256;
cfg.OscilSize=1024;
cfg.SwapStereo=0;
cfg.SampleRate = 44100;
cfg.SoundBufferSize = 256;
cfg.OscilSize = 1024;
cfg.SwapStereo = 0;
cfg.LinuxOSSWaveOutDev=new char[MAX_STRING_SIZE];
snprintf(cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE,"/dev/dsp");
cfg.LinuxOSSSeqInDev=new char[MAX_STRING_SIZE];
snprintf(cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE,"/dev/sequencer");
cfg.LinuxOSSWaveOutDev = new char[MAX_STRING_SIZE];
snprintf(cfg.LinuxOSSWaveOutDev, MAX_STRING_SIZE, "/dev/dsp");
cfg.LinuxOSSSeqInDev = new char[MAX_STRING_SIZE];
snprintf(cfg.LinuxOSSSeqInDev, MAX_STRING_SIZE, "/dev/sequencer");
cfg.DumpFile=new char[MAX_STRING_SIZE];
snprintf(cfg.DumpFile,MAX_STRING_SIZE,"zynaddsubfx_dump.txt");
cfg.DumpFile = new char[MAX_STRING_SIZE];
snprintf(cfg.DumpFile, MAX_STRING_SIZE, "zynaddsubfx_dump.txt");
cfg.WindowsWaveOutId=0;
cfg.WindowsMidiInId=0;
cfg.WindowsWaveOutId = 0;
cfg.WindowsMidiInId = 0;
cfg.BankUIAutoClose=0;
cfg.DumpNotesToFile=0;
cfg.DumpAppend=1;
cfg.BankUIAutoClose = 0;
cfg.DumpNotesToFile = 0;
cfg.DumpAppend = 1;
cfg.GzipCompression=3;
cfg.GzipCompression = 3;
cfg.Interpolation=0;
cfg.CheckPADsynth=1;
cfg.Interpolation = 0;
cfg.CheckPADsynth = 1;
cfg.UserInterfaceMode=0;
cfg.VirKeybLayout=1;
winwavemax=1;
winmidimax=1;
cfg.UserInterfaceMode = 0;
cfg.VirKeybLayout = 1;
winwavemax = 1;
winmidimax = 1;
//try to find out how many input midi devices are there
#ifdef WINMIDIIN
winmidimax=midiInGetNumDevs();
if (winmidimax==0) winmidimax=1;
winmidimax = midiInGetNumDevs();
if(winmidimax == 0)
winmidimax = 1;
#endif
winmididevices=new winmidionedevice[winmidimax];
for (int i=0;i<winmidimax;i++) {
winmididevices[i].name=new char[MAX_STRING_SIZE];
for (int j=0;j<MAX_STRING_SIZE;j++) winmididevices[i].name[j]='\0';
};
winmididevices = new winmidionedevice[winmidimax];
for(int i = 0; i < winmidimax; i++) {
winmididevices[i].name = new char[MAX_STRING_SIZE];
for(int j = 0; j < MAX_STRING_SIZE; j++)
winmididevices[i].name[j] = '\0';
}
//get the midi input devices name
#ifdef WINMIDIIN
MIDIINCAPS midiincaps;
for (int i=0;i<winmidimax;i++) {
if (! midiInGetDevCaps(i,&midiincaps,sizeof(MIDIINCAPS)))
snprintf(winmididevices[i].name,MAX_STRING_SIZE,"%s",midiincaps.szPname);
};
for(int i = 0; i < winmidimax; i++)
if(!midiInGetDevCaps(i, &midiincaps, sizeof(MIDIINCAPS)))
snprintf(winmididevices[i].name,
MAX_STRING_SIZE,
"%s",
midiincaps.szPname);
;
#endif
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) cfg.bankRootDirList[i]=NULL;
cfg.currentBankDir=new char[MAX_STRING_SIZE];
sprintf(cfg.currentBankDir,"./testbnk");
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
cfg.bankRootDirList[i] = NULL;
cfg.currentBankDir = new char[MAX_STRING_SIZE];
sprintf(cfg.currentBankDir, "./testbnk");
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) cfg.presetsDirList[i]=NULL;
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
cfg.presetsDirList[i] = NULL;
char filename[MAX_STRING_SIZE];
getConfigFileName(filename,MAX_STRING_SIZE);
getConfigFileName(filename, MAX_STRING_SIZE);
readConfig(filename);
if (cfg.bankRootDirList[0]==NULL) {
if(cfg.bankRootDirList[0] == NULL) {
#if defined(OS_LINUX)
//banks
cfg.bankRootDirList[0]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[0],"~/banks");
cfg.bankRootDirList[0] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[0], "~/banks");
cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[1],"./");
cfg.bankRootDirList[1] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[1], "./");
cfg.bankRootDirList[2]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[2],"/usr/share/zynaddsubfx/banks");
cfg.bankRootDirList[2] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[2], "/usr/share/zynaddsubfx/banks");
cfg.bankRootDirList[3]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[3],"/usr/local/share/zynaddsubfx/banks");
cfg.bankRootDirList[3] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[3], "/usr/local/share/zynaddsubfx/banks");
cfg.bankRootDirList[4]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[4],"../banks");
cfg.bankRootDirList[4] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[4], "../banks");
cfg.bankRootDirList[5]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[5],"banks");
cfg.bankRootDirList[5] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[5], "banks");
#else
//banks
cfg.bankRootDirList[0]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[0],"./");
cfg.bankRootDirList[0] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[0], "./");
#ifdef VSTAUDIOOUT
cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[1],"c:/Program Files/ZynAddSubFX/banks");
cfg.bankRootDirList[1] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[1], "c:/Program Files/ZynAddSubFX/banks");
#else
cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[1],"../banks");
cfg.bankRootDirList[1] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[1], "../banks");
#endif
cfg.bankRootDirList[2]=new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[2],"banks");
cfg.bankRootDirList[2] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[2], "banks");
#endif
};
}
if (cfg.presetsDirList[0]==NULL) {
if(cfg.presetsDirList[0] == NULL) {
#if defined(OS_LINUX)
//presets
cfg.presetsDirList[0]=new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[0],"./");
cfg.presetsDirList[0] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[0], "./");
cfg.presetsDirList[1]=new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[1],"../presets");
cfg.presetsDirList[1] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[1], "../presets");
cfg.presetsDirList[2]=new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[2],"presets");
cfg.presetsDirList[2] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[2], "presets");
cfg.presetsDirList[3]=new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[3],"/usr/share/zynaddsubfx/presets");
cfg.presetsDirList[3] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[3], "/usr/share/zynaddsubfx/presets");
cfg.presetsDirList[4]=new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[4],"/usr/local/share/zynaddsubfx/presets");
cfg.presetsDirList[4] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[4], "/usr/local/share/zynaddsubfx/presets");
#else
//presets
cfg.presetsDirList[0]=new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[0],"./");
cfg.presetsDirList[0] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[0], "./");
#ifdef VSTAUDIOOUT
cfg.presetsDirList[1]=new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[1],"c:/Program Files/ZynAddSubFX/presets");
cfg.presetsDirList[1] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[1], "c:/Program Files/ZynAddSubFX/presets");
#else
cfg.presetsDirList[1]=new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[1],"../presets");
cfg.presetsDirList[1] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[1], "../presets");
#endif
cfg.presetsDirList[2]=new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[2],"presets");
cfg.presetsDirList[2] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[2], "presets");
#endif
};
};
}
}
Config::~Config()
{
delete [] cfg.LinuxOSSWaveOutDev;
delete [] cfg.LinuxOSSSeqInDev;
delete [] cfg.DumpFile;
for (int i=0;i<winmidimax;i++) delete [] winmididevices[i].name;
for(int i = 0; i < winmidimax; i++)
delete [] winmididevices[i].name;
delete [] winmididevices;
};
}
void Config::save()
{
char filename[MAX_STRING_SIZE];
getConfigFileName(filename,MAX_STRING_SIZE);
getConfigFileName(filename, MAX_STRING_SIZE);
saveConfig(filename);
};
}
void Config::clearbankrootdirlist()
{
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
if (cfg.bankRootDirList[i]==NULL) delete(cfg.bankRootDirList[i]);
cfg.bankRootDirList[i]=NULL;
};
};
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) {
if(cfg.bankRootDirList[i] == NULL)
delete (cfg.bankRootDirList[i]);
cfg.bankRootDirList[i] = NULL;
}
}
void Config::clearpresetsdirlist()
{
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
if (cfg.presetsDirList[i]==NULL) delete(cfg.presetsDirList[i]);
cfg.presetsDirList[i]=NULL;
};
};
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) {
if(cfg.presetsDirList[i] == NULL)
delete (cfg.presetsDirList[i]);
cfg.presetsDirList[i] = NULL;
}
}
void Config::readConfig(const char *filename)
{
XMLwrapper *xmlcfg=new XMLwrapper();
if (xmlcfg->loadXMLfile(filename)<0) return;
if (xmlcfg->enterbranch("CONFIGURATION")) {
cfg.SampleRate=xmlcfg->getpar("sample_rate",cfg.SampleRate,4000,1024000);
cfg.SoundBufferSize=xmlcfg->getpar("sound_buffer_size",cfg.SoundBufferSize,16,8192);
cfg.OscilSize=xmlcfg->getpar("oscil_size",cfg.OscilSize,MAX_AD_HARMONICS*2,131072);
cfg.SwapStereo=xmlcfg->getpar("swap_stereo",cfg.SwapStereo,0,1);
cfg.BankUIAutoClose=xmlcfg->getpar("bank_window_auto_close",cfg.BankUIAutoClose,0,1);
XMLwrapper *xmlcfg = new XMLwrapper();
if(xmlcfg->loadXMLfile(filename) < 0)
return;
if(xmlcfg->enterbranch("CONFIGURATION")) {
cfg.SampleRate = xmlcfg->getpar("sample_rate",
cfg.SampleRate,
4000,
1024000);
cfg.SoundBufferSize = xmlcfg->getpar("sound_buffer_size",
cfg.SoundBufferSize,
16,
8192);
cfg.OscilSize = xmlcfg->getpar("oscil_size",
cfg.OscilSize,
MAX_AD_HARMONICS * 2,
131072);
cfg.SwapStereo = xmlcfg->getpar("swap_stereo",
cfg.SwapStereo,
0,
1);
cfg.BankUIAutoClose = xmlcfg->getpar("bank_window_auto_close",
cfg.BankUIAutoClose,
0,
1);
cfg.DumpNotesToFile=xmlcfg->getpar("dump_notes_to_file",cfg.DumpNotesToFile,0,1);
cfg.DumpAppend=xmlcfg->getpar("dump_append",cfg.DumpAppend,0,1);
xmlcfg->getparstr("dump_file",cfg.DumpFile,MAX_STRING_SIZE);
cfg.DumpNotesToFile = xmlcfg->getpar("dump_notes_to_file",
cfg.DumpNotesToFile,
0,
1);
cfg.DumpAppend = xmlcfg->getpar("dump_append",
cfg.DumpAppend,
0,
1);
xmlcfg->getparstr("dump_file", cfg.DumpFile, MAX_STRING_SIZE);
cfg.GzipCompression=xmlcfg->getpar("gzip_compression",cfg.GzipCompression,0,9);
cfg.GzipCompression = xmlcfg->getpar("gzip_compression",
cfg.GzipCompression,
0,
9);
xmlcfg->getparstr("bank_current",cfg.currentBankDir,MAX_STRING_SIZE);
cfg.Interpolation=xmlcfg->getpar("interpolation",cfg.Interpolation,0,1);
xmlcfg->getparstr("bank_current", cfg.currentBankDir, MAX_STRING_SIZE);
cfg.Interpolation = xmlcfg->getpar("interpolation",
cfg.Interpolation,
0,
1);
cfg.CheckPADsynth=xmlcfg->getpar("check_pad_synth",cfg.CheckPADsynth,0,1);
cfg.CheckPADsynth = xmlcfg->getpar("check_pad_synth",
cfg.CheckPADsynth,
0,
1);
cfg.UserInterfaceMode=xmlcfg->getpar("user_interface_mode",cfg.UserInterfaceMode,0,2);
cfg.VirKeybLayout=xmlcfg->getpar("virtual_keyboard_layout",cfg.VirKeybLayout,0,10);
cfg.UserInterfaceMode = xmlcfg->getpar("user_interface_mode",
cfg.UserInterfaceMode,
0,
2);
cfg.VirKeybLayout = xmlcfg->getpar("virtual_keyboard_layout",
cfg.VirKeybLayout,
0,
10);
//get bankroot dirs
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
if (xmlcfg->enterbranch("BANKROOT",i)) {
cfg.bankRootDirList[i]=new char[MAX_STRING_SIZE];
xmlcfg->getparstr("bank_root",cfg.bankRootDirList[i],MAX_STRING_SIZE);
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) {
if(xmlcfg->enterbranch("BANKROOT", i)) {
cfg.bankRootDirList[i] = new char[MAX_STRING_SIZE];
xmlcfg->getparstr("bank_root",
cfg.bankRootDirList[i],
MAX_STRING_SIZE);
xmlcfg->exitbranch();
};
};
}
}
//get preset root dirs
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
if (xmlcfg->enterbranch("PRESETSROOT",i)) {
cfg.presetsDirList[i]=new char[MAX_STRING_SIZE];
xmlcfg->getparstr("presets_root",cfg.presetsDirList[i],MAX_STRING_SIZE);
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) {
if(xmlcfg->enterbranch("PRESETSROOT", i)) {
cfg.presetsDirList[i] = new char[MAX_STRING_SIZE];
xmlcfg->getparstr("presets_root",
cfg.presetsDirList[i],
MAX_STRING_SIZE);
xmlcfg->exitbranch();
};
};
}
}
//linux stuff
xmlcfg->getparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE);
xmlcfg->getparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE);
xmlcfg->getparstr("linux_oss_wave_out_dev",
cfg.LinuxOSSWaveOutDev,
MAX_STRING_SIZE);
xmlcfg->getparstr("linux_oss_seq_in_dev",
cfg.LinuxOSSSeqInDev,
MAX_STRING_SIZE);
//windows stuff
cfg.WindowsWaveOutId=xmlcfg->getpar("windows_wave_out_id",cfg.WindowsWaveOutId,0,winwavemax);
cfg.WindowsMidiInId=xmlcfg->getpar("windows_midi_in_id",cfg.WindowsMidiInId,0,winmidimax);
cfg.WindowsWaveOutId = xmlcfg->getpar("windows_wave_out_id",
cfg.WindowsWaveOutId,
0,
winwavemax);
cfg.WindowsMidiInId = xmlcfg->getpar("windows_midi_in_id",
cfg.WindowsMidiInId,
0,
winmidimax);
xmlcfg->exitbranch();
};
delete(xmlcfg);
}
delete (xmlcfg);
cfg.OscilSize=(int) pow(2,ceil(log (cfg.OscilSize-1.0)/log(2.0)));
};
cfg.OscilSize = (int) pow(2, ceil(log(cfg.OscilSize - 1.0) / log(2.0)));
}
void Config::saveConfig(const char *filename)
{
XMLwrapper *xmlcfg=new XMLwrapper();
XMLwrapper *xmlcfg = new XMLwrapper();
xmlcfg->beginbranch("CONFIGURATION");
xmlcfg->addpar("sample_rate",cfg.SampleRate);
xmlcfg->addpar("sound_buffer_size",cfg.SoundBufferSize);
xmlcfg->addpar("oscil_size",cfg.OscilSize);
xmlcfg->addpar("swap_stereo",cfg.SwapStereo);
xmlcfg->addpar("bank_window_auto_close",cfg.BankUIAutoClose);
xmlcfg->addpar("sample_rate", cfg.SampleRate);
xmlcfg->addpar("sound_buffer_size", cfg.SoundBufferSize);
xmlcfg->addpar("oscil_size", cfg.OscilSize);
xmlcfg->addpar("swap_stereo", cfg.SwapStereo);
xmlcfg->addpar("bank_window_auto_close", cfg.BankUIAutoClose);
xmlcfg->addpar("dump_notes_to_file",cfg.DumpNotesToFile);
xmlcfg->addpar("dump_append",cfg.DumpAppend);
xmlcfg->addparstr("dump_file",cfg.DumpFile);
xmlcfg->addpar("dump_notes_to_file", cfg.DumpNotesToFile);
xmlcfg->addpar("dump_append", cfg.DumpAppend);
xmlcfg->addparstr("dump_file", cfg.DumpFile);
xmlcfg->addpar("gzip_compression",cfg.GzipCompression);
xmlcfg->addpar("gzip_compression", cfg.GzipCompression);
xmlcfg->addpar("check_pad_synth",cfg.CheckPADsynth);
xmlcfg->addpar("check_pad_synth", cfg.CheckPADsynth);
xmlcfg->addparstr("bank_current",cfg.currentBankDir);
xmlcfg->addparstr("bank_current", cfg.currentBankDir);
xmlcfg->addpar("user_interface_mode",cfg.UserInterfaceMode);
xmlcfg->addpar("virtual_keyboard_layout",cfg.VirKeybLayout);
xmlcfg->addpar("user_interface_mode", cfg.UserInterfaceMode);
xmlcfg->addpar("virtual_keyboard_layout", cfg.VirKeybLayout);
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.bankRootDirList[i]!=NULL) {
xmlcfg->beginbranch("BANKROOT",i);
xmlcfg->addparstr("bank_root",cfg.bankRootDirList[i]);
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
if(cfg.bankRootDirList[i] != NULL) {
xmlcfg->beginbranch("BANKROOT", i);
xmlcfg->addparstr("bank_root", cfg.bankRootDirList[i]);
xmlcfg->endbranch();
};
}
;
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.presetsDirList[i]!=NULL) {
xmlcfg->beginbranch("PRESETSROOT",i);
xmlcfg->addparstr("presets_root",cfg.presetsDirList[i]);
for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++)
if(cfg.presetsDirList[i] != NULL) {
xmlcfg->beginbranch("PRESETSROOT", i);
xmlcfg->addparstr("presets_root", cfg.presetsDirList[i]);
xmlcfg->endbranch();
};
}
;
xmlcfg->addpar("interpolation",cfg.Interpolation);
xmlcfg->addpar("interpolation", cfg.Interpolation);
//linux stuff
xmlcfg->addparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev);
xmlcfg->addparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev);
xmlcfg->addparstr("linux_oss_wave_out_dev", cfg.LinuxOSSWaveOutDev);
xmlcfg->addparstr("linux_oss_seq_in_dev", cfg.LinuxOSSSeqInDev);
//windows stuff
xmlcfg->addpar("windows_wave_out_id",cfg.WindowsWaveOutId);
xmlcfg->addpar("windows_midi_in_id",cfg.WindowsMidiInId);
xmlcfg->addpar("windows_wave_out_id", cfg.WindowsWaveOutId);
xmlcfg->addpar("windows_midi_in_id", cfg.WindowsMidiInId);
xmlcfg->endbranch();
int tmp=cfg.GzipCompression;
cfg.GzipCompression=0;
int tmp = cfg.GzipCompression;
cfg.GzipCompression = 0;
xmlcfg->saveXMLfile(filename);
cfg.GzipCompression=tmp;
cfg.GzipCompression = tmp;
delete(xmlcfg);
};
delete (xmlcfg);
}
void Config::getConfigFileName(char *name, int namesize)
{
name[0]=0;
name[0] = 0;
#ifdef OS_LINUX
snprintf(name,namesize,"%s%s",getenv("HOME"),"/.zynaddsubfxXML.cfg");
snprintf(name, namesize, "%s%s", getenv("HOME"), "/.zynaddsubfxXML.cfg");
#else
snprintf(name,namesize,"%s","zynaddsubfxXML.cfg");
snprintf(name, namesize, "%s", "zynaddsubfxXML.cfg");
#endif
};
}

View File

@@ -29,43 +29,43 @@
/**Configuration file functions*/
class Config
{
public:
/** Constructor*/
Config();
/** Destructor*/
~Config();
struct {
char *LinuxOSSWaveOutDev,*LinuxOSSSeqInDev;
int SampleRate,SoundBufferSize,OscilSize,SwapStereo;
int WindowsWaveOutId,WindowsMidiInId;
int BankUIAutoClose;
int DumpNotesToFile,DumpAppend;
int GzipCompression;
int Interpolation;
char *DumpFile;
char *bankRootDirList[MAX_BANK_ROOT_DIRS],*currentBankDir;
char *presetsDirList[MAX_BANK_ROOT_DIRS];
int CheckPADsynth;
int UserInterfaceMode;
int VirKeybLayout;
} cfg;
int winwavemax,winmidimax;//number of wave/midi devices on Windows
int maxstringsize;
public:
/** Constructor*/
Config();
/** Destructor*/
~Config();
struct {
char *LinuxOSSWaveOutDev, *LinuxOSSSeqInDev;
int SampleRate, SoundBufferSize, OscilSize, SwapStereo;
int WindowsWaveOutId, WindowsMidiInId;
int BankUIAutoClose;
int DumpNotesToFile, DumpAppend;
int GzipCompression;
int Interpolation;
char *DumpFile;
char *bankRootDirList[MAX_BANK_ROOT_DIRS], *currentBankDir;
char *presetsDirList[MAX_BANK_ROOT_DIRS];
int CheckPADsynth;
int UserInterfaceMode;
int VirKeybLayout;
} cfg;
int winwavemax, winmidimax; //number of wave/midi devices on Windows
int maxstringsize;
struct winmidionedevice {
char *name;
};
winmidionedevice *winmididevices;
struct winmidionedevice {
char *name;
};
winmidionedevice *winmididevices;
void clearbankrootdirlist();
void clearpresetsdirlist();
void init();
void save();
void clearbankrootdirlist();
void clearpresetsdirlist();
void init();
void save();
private:
void readConfig(const char *filename);
void saveConfig(const char *filename);
void getConfigFileName(char *name,int namesize);
private:
void readConfig(const char *filename);
void saveConfig(const char *filename);
void getConfigFileName(char *name, int namesize);
};
#endif

View File

@@ -27,74 +27,74 @@
class Control
{
public:
/**
* The parent is the logical owner of this control. Parent should only
* be null for the root node.
* The id is a string uniquely identifying this control within the
* context of the parent control. No spaces or dots are allowed in this
* id.
* Children id's are denoted by <parent-id>.<children-id>, so that one
* can refer to any control in the hierarchy by separating them with
* dots. Example: Main.AddSynth.FrequencyLFO.Amplitude
*/
Control(Control *parent, string id);
public:
/**
* The parent is the logical owner of this control. Parent should only
* be null for the root node.
* The id is a string uniquely identifying this control within the
* context of the parent control. No spaces or dots are allowed in this
* id.
* Children id's are denoted by <parent-id>.<children-id>, so that one
* can refer to any control in the hierarchy by separating them with
* dots. Example: Main.AddSynth.FrequencyLFO.Amplitude
*/
Control(Control *parent, string id);
/**
* Will recursively get the XML representation for all the subcontrols.
* Used for saving to file and copy-pasting settings
*/
string getXMLRepresentation();
/**
* Will recursively get the XML representation for all the subcontrols.
* Used for saving to file and copy-pasting settings
*/
string getXMLRepresentation();
/**
* Set the value of this (and possibly subcomponents as well) based on
* a xml description.
*/
void restoreFromXML(string xml);
/**
* Set the value of this (and possibly subcomponents as well) based on
* a xml description.
*/
void restoreFromXML(string xml);
/**
* Register a controluser. This will cause this user to be notified
* whenever the contents of the control changes.
*/
void registerControlUser(ControlUser *user);
/**
* This should return a string representation of the controls internal
* value
*/
virtual string getStringRepresentation() = 0;
/**
* Register a controluser. This will cause this user to be notified
* whenever the contents of the control changes.
*/
void registerControlUser(ControlUser *user);
/**
* This should return a string representation of the controls internal
* value
*/
virtual string getStringRepresentation() = 0;
};
class FloatControl : public Control
class FloatControl:public Control
{
public:
/**
* Set the value of this control. If the ControlUser variable is set,
* then this user will not be updated with the new value. This is to
* avoid setting a value being set back to the source that set it
* (which would be redundant, or possibly causing infinite setValue
* loops).
* NOTE: this function is thread-safe (using a mutex internally)
*/
void setValue(float value, ControlUser *user = NULL);
public:
/**
* Set the value of this control. If the ControlUser variable is set,
* then this user will not be updated with the new value. This is to
* avoid setting a value being set back to the source that set it
* (which would be redundant, or possibly causing infinite setValue
* loops).
* NOTE: this function is thread-safe (using a mutex internally)
*/
void setValue(float value, ControlUser *user = NULL);
/**
* Reimplemented from Control
*/
virtual string getStringRepresentation();
/**
* Reimplemented from Control
*/
virtual string getStringRepresentation();
float value();
float value();
};
class ControlUser
{
public:
/**
* Pure virtual method, to notify the controluser that the value has
* been changed internally, and needs to be read again.
*/
virtual void controlUpdated(Control *control) = 0;
public:
/**
* Pure virtual method, to notify the controluser that the value has
* been changed internally, and needs to be read again.
*/
virtual void controlUpdated(Control *control) = 0;
};
#endif /* _CONTROL_H_ */

View File

@@ -28,80 +28,97 @@ Dump dump;
Dump::Dump()
{
file=NULL;
tick=0;
k=0;
keyspressed=0;
};
file = NULL;
tick = 0;
k = 0;
keyspressed = 0;
}
Dump::~Dump()
{
if (file!=NULL) {
double duration=(double)tick*(double) SOUND_BUFFER_SIZE/(double) SAMPLE_RATE;
fprintf(file,"\n# statistics: duration = %d seconds; keyspressed = %d\n\n\n\n",(int) duration,keyspressed);
if(file != NULL) {
double duration = (double)tick * (double) SOUND_BUFFER_SIZE
/ (double) SAMPLE_RATE;
fprintf(
file,
"\n# statistics: duration = %d seconds; keyspressed = %d\n\n\n\n",
(int) duration,
keyspressed);
fclose(file);
};
};
}
}
void Dump::startnow()
{
if (file!=NULL) return;//the file is already open
if(file != NULL)
return; //the file is already open
if (config.cfg.DumpNotesToFile!=0) {
if (config.cfg.DumpAppend!=0) file=fopen(config.cfg.DumpFile,"a");
else file=fopen(config.cfg.DumpFile,"w");
if (file==NULL) return;
if (config.cfg.DumpAppend!=0) fprintf(file,"%s","#************************************\n");
if(config.cfg.DumpNotesToFile != 0) {
if(config.cfg.DumpAppend != 0)
file = fopen(config.cfg.DumpFile, "a");
else
file = fopen(config.cfg.DumpFile, "w");
if(file == NULL)
return;
if(config.cfg.DumpAppend != 0)
fprintf(file, "%s", "#************************************\n");
time_t tm=time(NULL);
time_t tm = time(NULL);
fprintf(file,"#date/time = %s\n",ctime(&tm));
fprintf(file,"#1 tick = %g milliseconds\n",SOUND_BUFFER_SIZE*1000.0/SAMPLE_RATE);
fprintf(file,"SAMPLERATE = %d\n",SAMPLE_RATE);
fprintf(file,"TICKSIZE = %d #samples\n",SOUND_BUFFER_SIZE);
fprintf(file,"\n\nSTART\n");
};
};
fprintf(file, "#date/time = %s\n", ctime(&tm));
fprintf(file,
"#1 tick = %g milliseconds\n",
SOUND_BUFFER_SIZE * 1000.0 / SAMPLE_RATE);
fprintf(file, "SAMPLERATE = %d\n", SAMPLE_RATE);
fprintf(file, "TICKSIZE = %d #samples\n", SOUND_BUFFER_SIZE);
fprintf(file, "\n\nSTART\n");
}
}
void Dump::inctick()
{
tick++;
};
}
void Dump::dumpnote(char chan,char note, char vel)
void Dump::dumpnote(char chan, char note, char vel)
{
if (file==NULL) return;
if (note==0) return;
if (vel==0) fprintf(file,"n %d -> %d %d \n",tick,chan,note);//note off
else fprintf(file,"N %d -> %d %d %d \n",tick,chan,note,vel);//note on
if(file == NULL)
return;
if(note == 0)
return;
if(vel == 0)
fprintf(file, "n %d -> %d %d \n", tick, chan, note); //note off
else
fprintf(file, "N %d -> %d %d %d \n", tick, chan, note, vel); //note on
if (vel!=0) keyspressed++;
if(vel != 0)
keyspressed++;
#ifndef JACKAUDIOOUT
if (k++>25) {
if(k++ > 25) {
fflush(file);
k=0;
};
k = 0;
}
#endif
};
}
void Dump::dumpcontroller(char chan,unsigned int type,int par)
void Dump::dumpcontroller(char chan, unsigned int type, int par)
{
if (file==NULL) return;
switch (type) {
if(file == NULL)
return;
switch(type) {
case C_pitchwheel:
fprintf(file,"P %d -> %d %d\n",tick,chan,par);
fprintf(file, "P %d -> %d %d\n", tick, chan, par);
break;
default:
fprintf(file,"C %d -> %d %d %d\n",tick,chan,type,par);
fprintf(file, "C %d -> %d %d %d\n", tick, chan, type, par);
break;
};
}
#ifndef JACKAUDIOOUT
if (k++>25) {
if(k++ > 25) {
fflush(file);
k=0;
};
k = 0;
}
#endif
};
}

View File

@@ -30,34 +30,35 @@
* \todo upgrade from stdio to iostream*/
class Dump
{
public:
/**Constructor*/
Dump();
/**Destructor
* Closes the dumpfile*/
~Dump();
/**Open dumpfile and prepare it for dumps
* \todo see if this fits better in the constructor*/
void startnow();
/**Tick the timestamp*/
void inctick();
/**Dump Note to dumpfile
* @param chan The channel of the note
* @param note The note
* @param vel The velocity of the note*/
void dumpnote(char chan,char note, char vel);
/** Dump the Controller
* @param chan The channel of the Controller
* @param type The type
* @param par The value of the controller
* \todo figure out what type is exactly meaning*/
void dumpcontroller(char chan,unsigned int type,int par);
public:
/**Constructor*/
Dump();
/**Destructor
* Closes the dumpfile*/
~Dump();
/**Open dumpfile and prepare it for dumps
* \todo see if this fits better in the constructor*/
void startnow();
/**Tick the timestamp*/
void inctick();
/**Dump Note to dumpfile
* @param chan The channel of the note
* @param note The note
* @param vel The velocity of the note*/
void dumpnote(char chan, char note, char vel);
/** Dump the Controller
* @param chan The channel of the Controller
* @param type The type
* @param par The value of the controller
* \todo figure out what type is exactly meaning*/
void dumpcontroller(char chan, unsigned int type, int par);
private:
FILE *file;
int tick;
int k;//This appears to be a constant used to flush the file
//periodically when JACK is used
int keyspressed;
private:
FILE *file;
int tick;
int k; //This appears to be a constant used to flush the file
//periodically when JACK is used
int keyspressed;
};
#endif

View File

@@ -26,7 +26,7 @@
#include "LASHClient.h"
LASHClient::LASHClient(int* argc, char*** argv)
LASHClient::LASHClient(int *argc, char ***argv)
{
client = lash_init(lash_extract_args(argc, argv), "ZynAddSubFX",
LASH_Config_File, LASH_PROTOCOL(2, 0));
@@ -35,56 +35,54 @@ LASHClient::LASHClient(int* argc, char*** argv)
void LASHClient::setalsaid(int id)
{
if (lash_enabled(client)) {
if (id != -1)
if(lash_enabled(client))
if(id != -1)
lash_alsa_client_id(client, id);
}
}
void LASHClient::setjackname(const char* name)
void LASHClient::setjackname(const char *name)
{
if (lash_enabled(client)) {
if (name != NULL) {
if(lash_enabled(client))
if(name != NULL) {
lash_jack_client_name(client, name);
lash_event_t *event = lash_event_new_with_type(LASH_Client_Name);
lash_event_set_string(event, name);
lash_send_event(client, event);
}
}
}
LASHClient::Event LASHClient::checkevents(std::string& filename)
LASHClient::Event LASHClient::checkevents(std::string &filename)
{
if (!lash_enabled(client))
if(!lash_enabled(client))
return NoEvent;
Event received = NoEvent;
lash_event_t* event;
while (event = lash_get_event(client)) {
lash_event_t *event;
while(event = lash_get_event(client)) {
// save
if (lash_event_get_type(event) == LASH_Save_File) {
std::cerr<<"LASH event: LASH_Save_File"<<std::endl;
filename = std::string(lash_event_get_string(event)) + "/master.xmz";
if(lash_event_get_type(event) == LASH_Save_File) {
std::cerr << "LASH event: LASH_Save_File" << std::endl;
filename = std::string(lash_event_get_string(event))
+ "/master.xmz";
received = Save;
break;
}
// restore
else if (lash_event_get_type(event) == LASH_Restore_File) {
std::cerr<<"LASH event: LASH_Restore_File"<<std::endl;
filename = std::string(lash_event_get_string(event)) + "/master.xmz";
else
if(lash_event_get_type(event) == LASH_Restore_File) {
std::cerr << "LASH event: LASH_Restore_File" << std::endl;
filename = std::string(lash_event_get_string(event))
+ "/master.xmz";
received = Restore;
break;
}
// quit
else if (lash_event_get_type(event) == LASH_Quit) {
std::cerr<<"LASH event: LASH_Quit"<<std::endl;
else
if(lash_event_get_type(event) == LASH_Quit) {
std::cerr << "LASH event: LASH_Quit" << std::endl;
received = Quit;
break;
}
@@ -97,8 +95,10 @@ LASHClient::Event LASHClient::checkevents(std::string& filename)
void LASHClient::confirmevent(Event event)
{
if (event == Save)
if(event == Save)
lash_send_event(client, lash_event_new_with_type(LASH_Save_File));
else if (event == Restore)
else
if(event == Restore)
lash_send_event(client, lash_event_new_with_type(LASH_Restore_File));
}

View File

@@ -33,32 +33,32 @@
* \todo see why there is no destructor*/
class LASHClient
{
public:
/**Enum to represent the LASH events that are currently handled*/
enum Event {
Save,
Restore,
Quit,
NoEvent
};
public:
/**Enum to represent the LASH events that are currently handled*/
enum Event {
Save,
Restore,
Quit,
NoEvent
};
/** Constructor
* @param argc number of arguments
* @param argv the text arguments*/
LASHClient(int* argc, char*** argv);
/** Constructor
* @param argc number of arguments
* @param argv the text arguments*/
LASHClient(int *argc, char ***argv);
/**set the ALSA id
* @param id new ALSA id*/
void setalsaid(int id);
/**Set the JACK name
* @param name the new name*/
void setjackname(const char* name);
Event checkevents(std::string& filename);
void confirmevent(Event event);
/**set the ALSA id
* @param id new ALSA id*/
void setalsaid(int id);
/**Set the JACK name
* @param name the new name*/
void setjackname(const char *name);
Event checkevents(std::string &filename);
void confirmevent(Event event);
private:
private:
lash_client_t* client;
lash_client_t *client;
};

File diff suppressed because it is too large Load Diff

View File

@@ -40,129 +40,136 @@ extern Dump dump;
* process them with system/insertion effects and mix them */
class Master
{
public:
/** Constructor*/
Master();
/** Destructor*/
~Master();
public:
/** Constructor*/
Master();
/** Destructor*/
~Master();
/**Saves all settings to a XML file
* @return 0 for ok or <0 if there is an error*/
int saveXML(const char *filename);
/**Saves all settings to a XML file
* @return 0 for ok or <0 if there is an error*/
int saveXML(const char *filename);
/**This adds the parameters to the XML data*/
void add2XML(XMLwrapper *xml);
/**This adds the parameters to the XML data*/
void add2XML(XMLwrapper *xml);
void defaults();
void defaults();
/**loads all settings from a XML file
* @return 0 for ok or -1 if there is an error*/
int loadXML(const char *filename);
void applyparameters();
/**loads all settings from a XML file
* @return 0 for ok or -1 if there is an error*/
int loadXML(const char *filename);
void applyparameters();
void getfromXML(XMLwrapper *xml);
void getfromXML(XMLwrapper *xml);
/**get all data to a newly allocated array (used for VST)
* @return the datasize*/
int getalldata(char **data);
/**put all data from the *data array to zynaddsubfx parameters (used for VST)*/
void putalldata(char *data,int size);
/**get all data to a newly allocated array (used for VST)
* @return the datasize*/
int getalldata(char **data);
/**put all data from the *data array to zynaddsubfx parameters (used for VST)*/
void putalldata(char *data, int size);
//Midi IN
void NoteOn(unsigned char chan,unsigned char note,unsigned char velocity);
void NoteOff(unsigned char chan,unsigned char note);
void SetController(unsigned char chan,unsigned int type,int par);
//void NRPN...
//Midi IN
void NoteOn(unsigned char chan,
unsigned char note,
unsigned char velocity);
void NoteOff(unsigned char chan, unsigned char note);
void SetController(unsigned char chan, unsigned int type, int par);
//void NRPN...
void ShutUp();
int shutup;
void ShutUp();
int shutup;
/**Audio Output*/
void AudioOut(REALTYPE *outl,REALTYPE *outr);
/**Audio Output (for callback mode). This allows the program to be controled by an external program*/
void GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr);
/**Audio Output*/
void AudioOut(REALTYPE *outl, REALTYPE *outr);
/**Audio Output (for callback mode). This allows the program to be controled by an external program*/
void GetAudioOutSamples(int nsamples,
int samplerate,
REALTYPE *outl,
REALTYPE *outr);
void partonoff(int npart,int what);
void partonoff(int npart, int what);
/**parts \todo see if this can be made to be dynamic*/
Part *part[NUM_MIDI_PARTS];
/**parts \todo see if this can be made to be dynamic*/
Part *part[NUM_MIDI_PARTS];
//parameters
unsigned char Pvolume;
unsigned char Pkeyshift;
unsigned char Psysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];
unsigned char Psysefxsend[NUM_SYS_EFX][NUM_SYS_EFX];
//parameters
unsigned char Pvolume;
unsigned char Pkeyshift;
unsigned char Psysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];
unsigned char Psysefxsend[NUM_SYS_EFX][NUM_SYS_EFX];
//parameters control
void setPvolume(char Pvolume_);
void setPkeyshift(char Pkeyshift_);
void setPsysefxvol(int Ppart,int Pefx,char Pvol);
void setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol);
//parameters control
void setPvolume(char Pvolume_);
void setPkeyshift(char Pkeyshift_);
void setPsysefxvol(int Ppart, int Pefx, char Pvol);
void setPsysefxsend(int Pefxfrom, int Pefxto, char Pvol);
//effects
EffectMgr *sysefx[NUM_SYS_EFX];//system
EffectMgr *insefx[NUM_INS_EFX];//insertion
//effects
EffectMgr *sysefx[NUM_SYS_EFX]; //system
EffectMgr *insefx[NUM_INS_EFX]; //insertion
// void swapcopyeffects(int what,int type,int neff1,int neff2);
//HDD recorder
Recorder HDDRecorder;
//HDD recorder
Recorder HDDRecorder;
//part that's apply the insertion effect; -1 to disable
short int Pinsparts[NUM_INS_EFX];
//part that's apply the insertion effect; -1 to disable
short int Pinsparts[NUM_INS_EFX];
//peaks for VU-meter
void vuresetpeaks();
REALTYPE vuoutpeakl,vuoutpeakr,vumaxoutpeakl,vumaxoutpeakr,vurmspeakl,vurmspeakr;
int vuclipped;
//peaks for VU-meter
void vuresetpeaks();
REALTYPE vuoutpeakl, vuoutpeakr, vumaxoutpeakl, vumaxoutpeakr,
vurmspeakl, vurmspeakr;
int vuclipped;
//peaks for part VU-meters
REALTYPE vuoutpeakpart[NUM_MIDI_PARTS];
unsigned char fakepeakpart[NUM_MIDI_PARTS];//this is used to compute the "peak" when the part is disabled
//peaks for part VU-meters
REALTYPE vuoutpeakpart[NUM_MIDI_PARTS];
unsigned char fakepeakpart[NUM_MIDI_PARTS]; //this is used to compute the "peak" when the part is disabled
Controller ctl;
int swaplr;//1 if L and R are swapped
Controller ctl;
int swaplr; //1 if L and R are swapped
//Sequencer
Sequencer seq;
//Sequencer
Sequencer seq;
//other objects
Microtonal microtonal;
Bank bank;
//other objects
Microtonal microtonal;
Bank bank;
FFTwrapper *fft;
pthread_mutex_t mutex;
FFTwrapper *fft;
pthread_mutex_t mutex;
private:
REALTYPE volume;
REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];
REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX];
private:
REALTYPE volume;
REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];
REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX];
//Temporary mixing samples for part samples which is sent to system effect
REALTYPE *tmpmixl;
REALTYPE *tmpmixr;
//Temporary mixing samples for part samples which is sent to system effect
REALTYPE *tmpmixl;
REALTYPE *tmpmixr;
int keyshift;
int keyshift;
//Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused)
REALTYPE *audiooutl;
REALTYPE *audiooutr;
//Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused)
REALTYPE *audiooutl;
REALTYPE *audiooutr;
int ksoundbuffersample;//this is used to know if there is need to call AudioOut by GetAudioOutSamples method
REALTYPE ksoundbuffersamplelow;//this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE)
REALTYPE oldsamplel,oldsampler;//this is used for resampling
//These are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard)
//and are called by internal parts of the program (like sequencer)
void noteon(unsigned char chan,unsigned char note,unsigned char velocity);
void noteoff(unsigned char chan,unsigned char note);
void setcontroller(unsigned char chan,unsigned int type,int par);
int ksoundbuffersample; //this is used to know if there is need to call AudioOut by GetAudioOutSamples method
REALTYPE ksoundbuffersamplelow; //this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE)
REALTYPE oldsamplel, oldsampler; //this is used for resampling
//These are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard)
//and are called by internal parts of the program (like sequencer)
void noteon(unsigned char chan,
unsigned char note,
unsigned char velocity);
void noteoff(unsigned char chan, unsigned char note);
void setcontroller(unsigned char chan, unsigned int type, int par);
};

View File

@@ -28,158 +28,190 @@
Microtonal::Microtonal()
{
Pname=new unsigned char[MICROTONAL_MAX_NAME_LEN];
Pcomment=new unsigned char[MICROTONAL_MAX_NAME_LEN];
Pname = new unsigned char[MICROTONAL_MAX_NAME_LEN];
Pcomment = new unsigned char[MICROTONAL_MAX_NAME_LEN];
defaults();
};
}
void Microtonal::defaults()
{
Pinvertupdown=0;
Pinvertupdowncenter=60;
octavesize=12;
Penabled=0;
PAnote=69;
PAfreq=440.0;
Pscaleshift=64;
Pinvertupdown = 0;
Pinvertupdowncenter = 60;
octavesize = 12;
Penabled = 0;
PAnote = 69;
PAfreq = 440.0;
Pscaleshift = 64;
Pfirstkey=0;
Plastkey=127;
Pmiddlenote=60;
Pmapsize=12;
Pmappingenabled=0;
Pfirstkey = 0;
Plastkey = 127;
Pmiddlenote = 60;
Pmapsize = 12;
Pmappingenabled = 0;
for (int i=0;i<128;i++) Pmapping[i]=i;
for(int i = 0; i < 128; i++)
Pmapping[i] = i;
for (int i=0;i<MAX_OCTAVE_SIZE;i++) {
octave[i].tuning=tmpoctave[i].tuning=pow(2,(i%octavesize+1)/12.0);
octave[i].type=tmpoctave[i].type=1;
octave[i].x1=tmpoctave[i].x1=(i%octavesize+1)*100;
octave[i].x2=tmpoctave[i].x2=0;
};
octave[11].type=2;
octave[11].x1=2;
octave[11].x2=1;
for (int i=0;i<MICROTONAL_MAX_NAME_LEN;i++) {
Pname[i]='\0';
Pcomment[i]='\0';
};
snprintf((char *) Pname,MICROTONAL_MAX_NAME_LEN,"12tET");
snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"Equal Temperament 12 notes per octave");
Pglobalfinedetune=64;
};
for(int i = 0; i < MAX_OCTAVE_SIZE; i++) {
octave[i].tuning = tmpoctave[i].tuning = pow(
2,
(i % octavesize
+ 1) / 12.0);
octave[i].type = tmpoctave[i].type = 1;
octave[i].x1 = tmpoctave[i].x1 = (i % octavesize + 1) * 100;
octave[i].x2 = tmpoctave[i].x2 = 0;
}
octave[11].type = 2;
octave[11].x1 = 2;
octave[11].x2 = 1;
for(int i = 0; i < MICROTONAL_MAX_NAME_LEN; i++) {
Pname[i] = '\0';
Pcomment[i] = '\0';
}
snprintf((char *) Pname, MICROTONAL_MAX_NAME_LEN, "12tET");
snprintf((char *) Pcomment,
MICROTONAL_MAX_NAME_LEN,
"Equal Temperament 12 notes per octave");
Pglobalfinedetune = 64;
}
Microtonal::~Microtonal()
{
delete [] Pname;
delete [] Pcomment;
};
}
/*
* Get the size of the octave
*/
unsigned char Microtonal::getoctavesize() const
{
if (Penabled!=0) return(octavesize);
else return(12);
};
if(Penabled != 0)
return octavesize;
else
return 12;
}
/*
* Get the frequency according the note number
*/
REALTYPE Microtonal::getnotefreq(int note,int keyshift) const
REALTYPE Microtonal::getnotefreq(int note, int keyshift) const
{
// in this function will appears many times things like this:
// var=(a+b*100)%b
// I had written this way because if I use var=a%b gives unwanted results when a<0
// This is the same with divisions.
if ((Pinvertupdown!=0)&&((Pmappingenabled==0)||(Penabled==0))) note=(int) Pinvertupdowncenter*2-note;
if((Pinvertupdown != 0) && ((Pmappingenabled == 0) || (Penabled == 0)))
note = (int) Pinvertupdowncenter * 2 - note;
//compute global fine detune
REALTYPE globalfinedetunerap=pow(2.0,(Pglobalfinedetune-64.0)/1200.0);//-64.0 .. 63.0 cents
REALTYPE globalfinedetunerap = pow(2.0, (Pglobalfinedetune - 64.0) / 1200.0); //-64.0 .. 63.0 cents
if (Penabled==0) return(pow(2.0,(note-PAnote+keyshift)/12.0)*PAfreq*globalfinedetunerap);//12tET
if(Penabled == 0)
return pow(2.0,
(note - PAnote
+ keyshift) / 12.0) * PAfreq * globalfinedetunerap; //12tET
int scaleshift=((int)Pscaleshift-64+(int) octavesize*100)%octavesize;
int scaleshift =
((int)Pscaleshift - 64 + (int) octavesize * 100) % octavesize;
//compute the keyshift
REALTYPE rap_keyshift=1.0;
if (keyshift!=0) {
int kskey=(keyshift+(int)octavesize*100)%octavesize;
int ksoct=(keyshift+(int)octavesize*100)/octavesize-100;
rap_keyshift=(kskey==0) ? (1.0):(octave[kskey-1].tuning);
rap_keyshift*=pow(octave[octavesize-1].tuning,ksoct);
};
REALTYPE rap_keyshift = 1.0;
if(keyshift != 0) {
int kskey = (keyshift + (int)octavesize * 100) % octavesize;
int ksoct = (keyshift + (int)octavesize * 100) / octavesize - 100;
rap_keyshift = (kskey == 0) ? (1.0) : (octave[kskey - 1].tuning);
rap_keyshift *= pow(octave[octavesize - 1].tuning, ksoct);
}
//if the mapping is enabled
if (Pmappingenabled!=0) {
if ((note<Pfirstkey)||(note>Plastkey)) return (-1.0);
if(Pmappingenabled != 0) {
if((note < Pfirstkey) || (note > Plastkey))
return -1.0;
//Compute how many mapped keys are from middle note to reference note
//and find out the proportion between the freq. of middle note and "A" note
int tmp=PAnote-Pmiddlenote,minus=0;
if (tmp<0) {
tmp=-tmp;
minus=1;
};
int deltanote=0;
for (int i=0;i<tmp;i++) if (Pmapping[i%Pmapsize]>=0) deltanote++;
REALTYPE rap_anote_middlenote=(deltanote==0) ? (1.0) : (octave[(deltanote-1)%octavesize].tuning);
if (deltanote!=0) rap_anote_middlenote*=pow(octave[octavesize-1].tuning,(deltanote-1)/octavesize);
if (minus!=0) rap_anote_middlenote=1.0/rap_anote_middlenote;
int tmp = PAnote - Pmiddlenote, minus = 0;
if(tmp < 0) {
tmp = -tmp;
minus = 1;
}
int deltanote = 0;
for(int i = 0; i < tmp; i++)
if(Pmapping[i % Pmapsize] >= 0)
deltanote++;
REALTYPE rap_anote_middlenote =
(deltanote ==
0) ? (1.0) : (octave[(deltanote - 1) % octavesize].tuning);
if(deltanote != 0)
rap_anote_middlenote *=
pow(octave[octavesize - 1].tuning, (deltanote - 1) / octavesize);
if(minus != 0)
rap_anote_middlenote = 1.0 / rap_anote_middlenote;
//Convert from note (midi) to degree (note from the tunning)
int degoct=(note-(int)Pmiddlenote+(int) Pmapsize*200)/(int)Pmapsize-200;
int degkey=(note-Pmiddlenote+(int)Pmapsize*100)%Pmapsize;
degkey=Pmapping[degkey];
if (degkey<0) return(-1.0);//this key is not mapped
int degoct =
(note - (int)Pmiddlenote + (int) Pmapsize
* 200) / (int)Pmapsize - 200;
int degkey = (note - Pmiddlenote + (int)Pmapsize * 100) % Pmapsize;
degkey = Pmapping[degkey];
if(degkey < 0)
return -1.0; //this key is not mapped
//invert the keyboard upside-down if it is asked for
//TODO: do the right way by using Pinvertupdowncenter
if (Pinvertupdown!=0) {
degkey=octavesize-degkey-1;
degoct=-degoct;
};
if(Pinvertupdown != 0) {
degkey = octavesize - degkey - 1;
degoct = -degoct;
}
//compute the frequency of the note
degkey=degkey+scaleshift;
degoct+=degkey/octavesize;
degkey%=octavesize;
degkey = degkey + scaleshift;
degoct += degkey / octavesize;
degkey %= octavesize;
REALTYPE freq=(degkey==0) ? (1.0):octave[degkey-1].tuning;
freq*=pow(octave[octavesize-1].tuning,degoct);
freq*=PAfreq/rap_anote_middlenote;
freq*=globalfinedetunerap;
if (scaleshift!=0) freq/=octave[scaleshift-1].tuning;
return(freq*rap_keyshift);
} else {//if the mapping is disabled
int nt=note-PAnote+scaleshift;
int ntkey=(nt+(int)octavesize*100)%octavesize;
int ntoct=(nt-ntkey)/octavesize;
REALTYPE freq = (degkey == 0) ? (1.0) : octave[degkey - 1].tuning;
freq *= pow(octave[octavesize - 1].tuning, degoct);
freq *= PAfreq / rap_anote_middlenote;
freq *= globalfinedetunerap;
if(scaleshift != 0)
freq /= octave[scaleshift - 1].tuning;
return freq * rap_keyshift;
}
else { //if the mapping is disabled
int nt = note - PAnote + scaleshift;
int ntkey = (nt + (int)octavesize * 100) % octavesize;
int ntoct = (nt - ntkey) / octavesize;
REALTYPE oct=octave[octavesize-1].tuning;
REALTYPE freq=octave[(ntkey+octavesize-1)%octavesize].tuning*pow(oct,ntoct)*PAfreq;
if (ntkey==0) freq/=oct;
if (scaleshift!=0) freq/=octave[scaleshift-1].tuning;
REALTYPE oct = octave[octavesize - 1].tuning;
REALTYPE freq =
octave[(ntkey + octavesize - 1) % octavesize].tuning *pow(oct,
ntoct)
* PAfreq;
if(ntkey == 0)
freq /= oct;
if(scaleshift != 0)
freq /= octave[scaleshift - 1].tuning;
// fprintf(stderr,"note=%d freq=%.3f cents=%d\n",note,freq,(int)floor(log(freq/PAfreq)/log(2.0)*1200.0+0.5));
freq*=globalfinedetunerap;
return(freq*rap_keyshift);
};
};
freq *= globalfinedetunerap;
return freq * rap_keyshift;
}
}
bool Microtonal::operator==(const Microtonal &micro) const
{
return(!(*this!=micro));
return !(*this != micro);
}
bool Microtonal::operator!=(const Microtonal &micro) const
{
//A simple macro to test equality MiCRotonal EQuals (not the perfect
//approach, but good enough)
#define MCREQ( x ) if(x!=micro.x)return true;
#define MCREQ(x) if(x != micro.x) \
return true;
//for floats
#define FMCREQ( x ) if(!((x<micro.x+0.0001)&&(x>micro.x-0.0001)))return true;
#define FMCREQ(x) if(!((x < micro.x + 0.0001) && (x > micro.x - 0.0001))) \
return true;
MCREQ(Pinvertupdown);
MCREQ(Pinvertupdowncenter);
@@ -195,18 +227,18 @@ bool Microtonal::operator!=(const Microtonal &micro) const
MCREQ(Pmapsize);
MCREQ(Pmappingenabled);
for (int i=0;i<128;i++)
for(int i = 0; i < 128; i++)
MCREQ(Pmapping[i]);
for (int i=0;i<octavesize;i++) {
for(int i = 0; i < octavesize; i++) {
FMCREQ(octave[i].tuning);
MCREQ(octave[i].type);
MCREQ(octave[i].x1);
MCREQ(octave[i].x2);
}
if(strcmp((const char *)this->Pname,(const char *)micro.Pname))
if(strcmp((const char *)this->Pname, (const char *)micro.Pname))
return true;
if(strcmp((const char *)this->Pcomment,(const char *)micro.Pcomment))
if(strcmp((const char *)this->Pcomment, (const char *)micro.Pcomment))
return true;
MCREQ(Pglobalfinedetune);
return false;
@@ -214,384 +246,442 @@ bool Microtonal::operator!=(const Microtonal &micro) const
//undefine macros, as they are no longer needed
#undef MCREQ
#undef FMCREQ
}
/*
* Convert a line to tunings; returns -1 if it ok
*/
int Microtonal::linetotunings(unsigned int nline,const char *line)
int Microtonal::linetotunings(unsigned int nline, const char *line)
{
int x1=-1,x2=-1,type=-1;
REALTYPE x=-1.0,tmp,tuning=1.0;
if (strstr(line,"/")==NULL) {
if (strstr(line,".")==NULL) {// M case (M=M/1)
sscanf(line,"%d",&x1);
x2=1;
type=2;//division
} else {// float number case
sscanf(line,"%f",&x);
if (x<0.000001) return(1);
type=1;//float type(cents)
};
} else {// M/N case
sscanf(line,"%d/%d",&x1,&x2);
if ((x1<0)||(x2<0)) return(1);
if (x2==0) x2=1;
type=2;//division
};
int x1 = -1, x2 = -1, type = -1;
REALTYPE x = -1.0, tmp, tuning = 1.0;
if(strstr(line, "/") == NULL) {
if(strstr(line, ".") == NULL) { // M case (M=M/1)
sscanf(line, "%d", &x1);
x2 = 1;
type = 2; //division
}
else { // float number case
sscanf(line, "%f", &x);
if(x < 0.000001)
return 1;
type = 1; //float type(cents)
}
}
else { // M/N case
sscanf(line, "%d/%d", &x1, &x2);
if((x1 < 0) || (x2 < 0))
return 1;
if(x2 == 0)
x2 = 1;
type = 2; //division
}
if (x1<=0) x1=1;//not allow zero frequency sounds (consider 0 as 1)
if(x1 <= 0)
x1 = 1; //not allow zero frequency sounds (consider 0 as 1)
//convert to float if the number are too big
if ((type==2)&&((x1>(128*128*128-1))||(x2>(128*128*128-1)))) {
type=1;
x=((REALTYPE) x1)/x2;
};
switch (type) {
if((type == 2)
&& ((x1 > (128 * 128 * 128 - 1)) || (x2 > (128 * 128 * 128 - 1)))) {
type = 1;
x = ((REALTYPE) x1) / x2;
}
switch(type) {
case 1:
x1=(int) floor(x);
tmp=fmod(x,1.0);
x2=(int) (floor (tmp*1e6));
tuning=pow(2.0,x/1200.0);
x1 = (int) floor(x);
tmp = fmod(x, 1.0);
x2 = (int) (floor(tmp * 1e6));
tuning = pow(2.0, x / 1200.0);
break;
case 2:
x=((REALTYPE)x1)/x2;
tuning=x;
x = ((REALTYPE)x1) / x2;
tuning = x;
break;
};
}
tmpoctave[nline].tuning=tuning;
tmpoctave[nline].type=type;
tmpoctave[nline].x1=x1;
tmpoctave[nline].x2=x2;
tmpoctave[nline].tuning = tuning;
tmpoctave[nline].type = type;
tmpoctave[nline].x1 = x1;
tmpoctave[nline].x2 = x2;
return(-1);//ok
};
return -1; //ok
}
/*
* Convert the text to tunnings
*/
int Microtonal::texttotunings(const char *text)
{
unsigned int i,k=0,nl=0;
unsigned int i, k = 0, nl = 0;
char *lin;
lin=new char[MAX_LINE_SIZE+1];
while (k<strlen(text)) {
for (i=0;i<MAX_LINE_SIZE;i++) {
lin[i]=text[k++];
if (lin[i]<0x20) break;
};
lin[i]='\0';
if (strlen(lin)==0) continue;
int err=linetotunings(nl,lin);
if (err!=-1) {
lin = new char[MAX_LINE_SIZE + 1];
while(k < strlen(text)) {
for(i = 0; i < MAX_LINE_SIZE; i++) {
lin[i] = text[k++];
if(lin[i] < 0x20)
break;
}
lin[i] = '\0';
if(strlen(lin) == 0)
continue;
int err = linetotunings(nl, lin);
if(err != -1) {
delete [] lin;
return(nl);//Parse error
};
return nl; //Parse error
}
nl++;
};
}
delete [] lin;
if (nl>MAX_OCTAVE_SIZE) nl=MAX_OCTAVE_SIZE;
if (nl==0) return(-2);//the input is empty
octavesize=nl;
for (i=0;i<octavesize;i++) {
octave[i].tuning=tmpoctave[i].tuning;
octave[i].type=tmpoctave[i].type;
octave[i].x1=tmpoctave[i].x1;
octave[i].x2=tmpoctave[i].x2;
};
return(-1);//ok
};
if(nl > MAX_OCTAVE_SIZE)
nl = MAX_OCTAVE_SIZE;
if(nl == 0)
return -2; //the input is empty
octavesize = nl;
for(i = 0; i < octavesize; i++) {
octave[i].tuning = tmpoctave[i].tuning;
octave[i].type = tmpoctave[i].type;
octave[i].x1 = tmpoctave[i].x1;
octave[i].x2 = tmpoctave[i].x2;
}
return -1; //ok
}
/*
* Convert the text to mapping
*/
void Microtonal::texttomapping(const char *text)
{
unsigned int i,k=0;
unsigned int i, k = 0;
char *lin;
lin=new char[MAX_LINE_SIZE+1];
for (i=0;i<128;i++) Pmapping[i]=-1;
int tx=0;
while (k<strlen(text)) {
for (i=0;i<MAX_LINE_SIZE;i++) {
lin[i]=text[k++];
if (lin[i]<0x20) break;
};
lin[i]='\0';
if (strlen(lin)==0) continue;
lin = new char[MAX_LINE_SIZE + 1];
for(i = 0; i < 128; i++)
Pmapping[i] = -1;
int tx = 0;
while(k < strlen(text)) {
for(i = 0; i < MAX_LINE_SIZE; i++) {
lin[i] = text[k++];
if(lin[i] < 0x20)
break;
}
lin[i] = '\0';
if(strlen(lin) == 0)
continue;
int tmp=0;
if (sscanf(lin,"%d",&tmp)==0) tmp=-1;
if (tmp<-1) tmp=-1;
Pmapping[tx]=tmp;
int tmp = 0;
if(sscanf(lin, "%d", &tmp) == 0)
tmp = -1;
if(tmp < -1)
tmp = -1;
Pmapping[tx] = tmp;
if ((tx++)>127) break;
};
if((tx++) > 127)
break;
}
delete [] lin;
if (tx==0) tx=1;
Pmapsize=tx;
};
if(tx == 0)
tx = 1;
Pmapsize = tx;
}
/*
* Convert tunning to text line
*/
void Microtonal::tuningtoline(int n,char *line,int maxn)
void Microtonal::tuningtoline(int n, char *line, int maxn)
{
if ((n>octavesize) || (n>MAX_OCTAVE_SIZE)) {
line[0]='\0';
if((n > octavesize) || (n > MAX_OCTAVE_SIZE)) {
line[0] = '\0';
return;
};
if (octave[n].type==1) snprintf(line,maxn,"%d.%d",octave[n].x1,octave[n].x2);
if (octave[n].type==2) snprintf(line,maxn,"%d/%d",octave[n].x1,octave[n].x2);
};
}
if(octave[n].type == 1)
snprintf(line, maxn, "%d.%d", octave[n].x1, octave[n].x2);
if(octave[n].type == 2)
snprintf(line, maxn, "%d/%d", octave[n].x1, octave[n].x2);
}
int Microtonal::loadline(FILE *file,char *line)
int Microtonal::loadline(FILE *file, char *line)
{
do {
if (fgets(line,500,file)==0) return(1);
} while (line[0]=='!');
return(0);
};
if(fgets(line, 500, file) == 0)
return 1;
} while(line[0] == '!');
return 0;
}
/*
* Loads the tunnings from a scl file
*/
int Microtonal::loadscl(const char *filename)
{
FILE *file=fopen(filename, "r");
char tmp[500];
fseek(file,0,SEEK_SET);
FILE *file = fopen(filename, "r");
char tmp[500];
fseek(file, 0, SEEK_SET);
//loads the short description
if (loadline(file,&tmp[0])!=0) return(2);
for (int i=0;i<500;i++) if (tmp[i]<32) tmp[i]=0;
snprintf((char *) Pname,MICROTONAL_MAX_NAME_LEN,"%s",tmp);
snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"%s",tmp);
if(loadline(file, &tmp[0]) != 0)
return 2;
for(int i = 0; i < 500; i++)
if(tmp[i] < 32)
tmp[i] = 0;
snprintf((char *) Pname, MICROTONAL_MAX_NAME_LEN, "%s", tmp);
snprintf((char *) Pcomment, MICROTONAL_MAX_NAME_LEN, "%s", tmp);
//loads the number of the notes
if (loadline(file,&tmp[0])!=0) return(2);
int nnotes=MAX_OCTAVE_SIZE;
sscanf(&tmp[0],"%d",&nnotes);
if (nnotes>MAX_OCTAVE_SIZE) return (2);
if(loadline(file, &tmp[0]) != 0)
return 2;
int nnotes = MAX_OCTAVE_SIZE;
sscanf(&tmp[0], "%d", &nnotes);
if(nnotes > MAX_OCTAVE_SIZE)
return 2;
//load the tunnings
for (int nline=0;nline<nnotes;nline++) {
if (loadline(file,&tmp[0])!=0) return(2);
linetotunings(nline,&tmp[0]);
};
for(int nline = 0; nline < nnotes; nline++) {
if(loadline(file, &tmp[0]) != 0)
return 2;
linetotunings(nline, &tmp[0]);
}
fclose(file);
octavesize=nnotes;
for (int i=0;i<octavesize;i++) {
octave[i].tuning=tmpoctave[i].tuning;
octave[i].type=tmpoctave[i].type;
octave[i].x1=tmpoctave[i].x1;
octave[i].x2=tmpoctave[i].x2;
};
octavesize = nnotes;
for(int i = 0; i < octavesize; i++) {
octave[i].tuning = tmpoctave[i].tuning;
octave[i].type = tmpoctave[i].type;
octave[i].x1 = tmpoctave[i].x1;
octave[i].x2 = tmpoctave[i].x2;
}
return(0);
};
return 0;
}
/*
* Loads the mapping from a kbm file
*/
int Microtonal::loadkbm(const char *filename)
{
FILE *file=fopen(filename, "r");
int x;
char tmp[500];
FILE *file = fopen(filename, "r");
int x;
char tmp[500];
fseek(file,0,SEEK_SET);
fseek(file, 0, SEEK_SET);
//loads the mapsize
if (loadline(file,&tmp[0])!=0) return(2);
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
if (x<1) x=0;
if (x>127) x=127;//just in case...
Pmapsize=x;
if(loadline(file, &tmp[0]) != 0)
return 2;
if(sscanf(&tmp[0], "%d", &x) == 0)
return 2;
if(x < 1)
x = 0;
if(x > 127)
x = 127; //just in case...
Pmapsize = x;
//loads first MIDI note to retune
if (loadline(file,&tmp[0])!=0) return(2);
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
if (x<1) x=0;
if (x>127) x=127;//just in case...
Pfirstkey=x;
if(loadline(file, &tmp[0]) != 0)
return 2;
if(sscanf(&tmp[0], "%d", &x) == 0)
return 2;
if(x < 1)
x = 0;
if(x > 127)
x = 127; //just in case...
Pfirstkey = x;
//loads last MIDI note to retune
if (loadline(file,&tmp[0])!=0) return(2);
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
if (x<1) x=0;
if (x>127) x=127;//just in case...
Plastkey=x;
if(loadline(file, &tmp[0]) != 0)
return 2;
if(sscanf(&tmp[0], "%d", &x) == 0)
return 2;
if(x < 1)
x = 0;
if(x > 127)
x = 127; //just in case...
Plastkey = x;
//loads last the middle note where scale fro scale degree=0
if (loadline(file,&tmp[0])!=0) return(2);
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
if (x<1) x=0;
if (x>127) x=127;//just in case...
Pmiddlenote=x;
if(loadline(file, &tmp[0]) != 0)
return 2;
if(sscanf(&tmp[0], "%d", &x) == 0)
return 2;
if(x < 1)
x = 0;
if(x > 127)
x = 127; //just in case...
Pmiddlenote = x;
//loads the reference note
if (loadline(file,&tmp[0])!=0) return(2);
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
if (x<1) x=0;
if (x>127) x=127;//just in case...
PAnote=x;
if(loadline(file, &tmp[0]) != 0)
return 2;
if(sscanf(&tmp[0], "%d", &x) == 0)
return 2;
if(x < 1)
x = 0;
if(x > 127)
x = 127; //just in case...
PAnote = x;
//loads the reference freq.
if (loadline(file,&tmp[0])!=0) return(2);
REALTYPE tmpPAfreq=440.0;
if (sscanf(&tmp[0],"%f",&tmpPAfreq)==0) return(2);
PAfreq=tmpPAfreq;
if(loadline(file, &tmp[0]) != 0)
return 2;
REALTYPE tmpPAfreq = 440.0;
if(sscanf(&tmp[0], "%f", &tmpPAfreq) == 0)
return 2;
PAfreq = tmpPAfreq;
//the scale degree(which is the octave) is not loaded, it is obtained by the tunnings with getoctavesize() method
if (loadline(file,&tmp[0])!=0) return(2);
if(loadline(file, &tmp[0]) != 0)
return 2;
//load the mappings
if (Pmapsize!=0) {
for (int nline=0;nline<Pmapsize;nline++) {
if (loadline(file,&tmp[0])!=0) return(2);
if (sscanf(&tmp[0],"%d",&x)==0) x=-1;
Pmapping[nline]=x;
};
Pmappingenabled=1;
} else {
Pmappingenabled=0;
Pmapping[0]=0;
Pmapsize=1;
};
if(Pmapsize != 0) {
for(int nline = 0; nline < Pmapsize; nline++) {
if(loadline(file, &tmp[0]) != 0)
return 2;
if(sscanf(&tmp[0], "%d", &x) == 0)
x = -1;
Pmapping[nline] = x;
}
Pmappingenabled = 1;
}
else {
Pmappingenabled = 0;
Pmapping[0] = 0;
Pmapsize = 1;
}
fclose(file);
return(0);
};
return 0;
}
void Microtonal::add2XML(XMLwrapper *xml)const
void Microtonal::add2XML(XMLwrapper *xml) const
{
xml->addparstr("name",(char *) Pname);
xml->addparstr("comment",(char *) Pcomment);
xml->addparstr("name", (char *) Pname);
xml->addparstr("comment", (char *) Pcomment);
xml->addparbool("invert_up_down",Pinvertupdown);
xml->addpar("invert_up_down_center",Pinvertupdowncenter);
xml->addparbool("invert_up_down", Pinvertupdown);
xml->addpar("invert_up_down_center", Pinvertupdowncenter);
xml->addparbool("enabled",Penabled);
xml->addpar("global_fine_detune",Pglobalfinedetune);
xml->addparbool("enabled", Penabled);
xml->addpar("global_fine_detune", Pglobalfinedetune);
xml->addpar("a_note",PAnote);
xml->addparreal("a_freq",PAfreq);
xml->addpar("a_note", PAnote);
xml->addparreal("a_freq", PAfreq);
if ((Penabled==0)&&(xml->minimal)) return;
if((Penabled == 0) && (xml->minimal))
return;
xml->beginbranch("SCALE");
xml->addpar("scale_shift",Pscaleshift);
xml->addpar("first_key",Pfirstkey);
xml->addpar("last_key",Plastkey);
xml->addpar("middle_note",Pmiddlenote);
xml->addpar("scale_shift", Pscaleshift);
xml->addpar("first_key", Pfirstkey);
xml->addpar("last_key", Plastkey);
xml->addpar("middle_note", Pmiddlenote);
xml->beginbranch("OCTAVE");
xml->addpar("octave_size",octavesize);
for (int i=0;i<octavesize;i++) {
xml->beginbranch("DEGREE",i);
if (octave[i].type==1) {
xml->addparreal("cents",octave[i].tuning);
};
if (octave[i].type==2) {
xml->addpar("numerator",octave[i].x1);
xml->addpar("denominator",octave[i].x2);
};
xml->addpar("octave_size", octavesize);
for(int i = 0; i < octavesize; i++) {
xml->beginbranch("DEGREE", i);
if(octave[i].type == 1)
xml->addparreal("cents", octave[i].tuning);
;
if(octave[i].type == 2) {
xml->addpar("numerator", octave[i].x1);
xml->addpar("denominator", octave[i].x2);
}
xml->endbranch();
};
}
xml->endbranch();
xml->beginbranch("KEYBOARD_MAPPING");
xml->addpar("map_size",Pmapsize);
xml->addpar("mapping_enabled",Pmappingenabled);
for (int i=0;i<Pmapsize;i++) {
xml->beginbranch("KEYMAP",i);
xml->addpar("degree",Pmapping[i]);
xml->addpar("map_size", Pmapsize);
xml->addpar("mapping_enabled", Pmappingenabled);
for(int i = 0; i < Pmapsize; i++) {
xml->beginbranch("KEYMAP", i);
xml->addpar("degree", Pmapping[i]);
xml->endbranch();
};
}
xml->endbranch();
xml->endbranch();
};
}
void Microtonal::getfromXML(XMLwrapper *xml)
{
xml->getparstr("name",(char *) Pname,MICROTONAL_MAX_NAME_LEN);
xml->getparstr("comment",(char *) Pcomment,MICROTONAL_MAX_NAME_LEN);
xml->getparstr("name", (char *) Pname, MICROTONAL_MAX_NAME_LEN);
xml->getparstr("comment", (char *) Pcomment, MICROTONAL_MAX_NAME_LEN);
Pinvertupdown=xml->getparbool("invert_up_down",Pinvertupdown);
Pinvertupdowncenter=xml->getpar127("invert_up_down_center",Pinvertupdowncenter);
Pinvertupdown = xml->getparbool("invert_up_down", Pinvertupdown);
Pinvertupdowncenter = xml->getpar127("invert_up_down_center",
Pinvertupdowncenter);
Penabled=xml->getparbool("enabled",Penabled);
Pglobalfinedetune=xml->getpar127("global_fine_detune",Pglobalfinedetune);
Penabled = xml->getparbool("enabled", Penabled);
Pglobalfinedetune = xml->getpar127("global_fine_detune", Pglobalfinedetune);
PAnote=xml->getpar127("a_note",PAnote);
PAfreq=xml->getparreal("a_freq",PAfreq,1.0,10000.0);
PAnote = xml->getpar127("a_note", PAnote);
PAfreq = xml->getparreal("a_freq", PAfreq, 1.0, 10000.0);
if (xml->enterbranch("SCALE")) {
Pscaleshift=xml->getpar127("scale_shift",Pscaleshift);
Pfirstkey=xml->getpar127("first_key",Pfirstkey);
Plastkey=xml->getpar127("last_key",Plastkey);
Pmiddlenote=xml->getpar127("middle_note",Pmiddlenote);
if(xml->enterbranch("SCALE")) {
Pscaleshift = xml->getpar127("scale_shift", Pscaleshift);
Pfirstkey = xml->getpar127("first_key", Pfirstkey);
Plastkey = xml->getpar127("last_key", Plastkey);
Pmiddlenote = xml->getpar127("middle_note", Pmiddlenote);
if (xml->enterbranch("OCTAVE")) {
octavesize=xml->getpar127("octave_size",octavesize);
for (int i=0;i<octavesize;i++) {
if (xml->enterbranch("DEGREE",i)==0) continue;
octave[i].x2=0;
octave[i].tuning=xml->getparreal("cents",octave[i].tuning);
octave[i].x1=xml->getpar127("numerator",octave[i].x1);
octave[i].x2=xml->getpar127("denominator",octave[i].x2);
if(xml->enterbranch("OCTAVE")) {
octavesize = xml->getpar127("octave_size", octavesize);
for(int i = 0; i < octavesize; i++) {
if(xml->enterbranch("DEGREE", i) == 0)
continue;
octave[i].x2 = 0;
octave[i].tuning = xml->getparreal("cents", octave[i].tuning);
octave[i].x1 = xml->getpar127("numerator", octave[i].x1);
octave[i].x2 = xml->getpar127("denominator", octave[i].x2);
if (octave[i].x2!=0) octave[i].type=2;
else octave[i].type=1;
if(octave[i].x2 != 0)
octave[i].type = 2;
else
octave[i].type = 1;
xml->exitbranch();
};
}
xml->exitbranch();
};
}
if (xml->enterbranch("KEYBOARD_MAPPING")) {
Pmapsize=xml->getpar127("map_size",Pmapsize);
Pmappingenabled=xml->getpar127("mapping_enabled",Pmappingenabled);
for (int i=0;i<Pmapsize;i++) {
if (xml->enterbranch("KEYMAP",i)==0) continue;
Pmapping[i]=xml->getpar127("degree",Pmapping[i]);
if(xml->enterbranch("KEYBOARD_MAPPING")) {
Pmapsize = xml->getpar127("map_size", Pmapsize);
Pmappingenabled = xml->getpar127("mapping_enabled", Pmappingenabled);
for(int i = 0; i < Pmapsize; i++) {
if(xml->enterbranch("KEYMAP", i) == 0)
continue;
Pmapping[i] = xml->getpar127("degree", Pmapping[i]);
xml->exitbranch();
};
}
xml->exitbranch();
};
}
xml->exitbranch();
};
};
}
}
int Microtonal::saveXML(const char *filename)const
int Microtonal::saveXML(const char *filename) const
{
XMLwrapper *xml=new XMLwrapper();
XMLwrapper *xml = new XMLwrapper();
xml->beginbranch("MICROTONAL");
add2XML(xml);
xml->endbranch();
int result=xml->saveXMLfile(filename);
int result = xml->saveXMLfile(filename);
delete (xml);
return(result);
};
return result;
}
int Microtonal::loadXML(const char *filename)
{
XMLwrapper *xml=new XMLwrapper();
if (xml->loadXMLfile(filename)<0) {
delete(xml);
return(-1);
};
XMLwrapper *xml = new XMLwrapper();
if(xml->loadXMLfile(filename) < 0) {
delete (xml);
return -1;
}
if (xml->enterbranch("MICROTONAL")==0) return(-10);
if(xml->enterbranch("MICROTONAL") == 0)
return -10;
getfromXML(xml);
xml->exitbranch();
delete(xml);
return(0);
};
delete (xml);
return 0;
}

View File

@@ -35,102 +35,100 @@
/**Tuning settings and microtonal capabilities*/
class Microtonal
{
public:
/**Constructor*/
Microtonal();
/**Destructor*/
~Microtonal();
void defaults();
/**Calculates the frequency for a given note
*/
REALTYPE getnotefreq(int note,int keyshift) const;
public:
/**Constructor*/
Microtonal();
/**Destructor*/
~Microtonal();
void defaults();
/**Calculates the frequency for a given note
*/
REALTYPE getnotefreq(int note, int keyshift) const;
//Parameters
/**if the keys are inversed (the pitch is lower to keys from the right direction)*/
unsigned char Pinvertupdown;
//Parameters
/**if the keys are inversed (the pitch is lower to keys from the right direction)*/
unsigned char Pinvertupdown;
/**the central key of the inversion*/
unsigned char Pinvertupdowncenter;
/**the central key of the inversion*/
unsigned char Pinvertupdowncenter;
/**0 for 12 key temperate scale, 1 for microtonal*/
unsigned char Penabled;
/**0 for 12 key temperate scale, 1 for microtonal*/
unsigned char Penabled;
/**the note of "A" key*/
unsigned char PAnote;
/**the note of "A" key*/
unsigned char PAnote;
/**the frequency of the "A" note*/
REALTYPE PAfreq;
/**the frequency of the "A" note*/
REALTYPE PAfreq;
/**if the scale is "tuned" to a note, you can tune to other note*/
unsigned char Pscaleshift;
/**if the scale is "tuned" to a note, you can tune to other note*/
unsigned char Pscaleshift;
//first and last key (to retune)
unsigned char Pfirstkey;
unsigned char Plastkey;
//first and last key (to retune)
unsigned char Pfirstkey;
unsigned char Plastkey;
/**The middle note where scale degree 0 is mapped to*/
unsigned char Pmiddlenote;
/**The middle note where scale degree 0 is mapped to*/
unsigned char Pmiddlenote;
/**Map size*/
unsigned char Pmapsize;
/**Map size*/
unsigned char Pmapsize;
/**Mapping ON/OFF*/
unsigned char Pmappingenabled;
/**Mapping (keys)*/
short int Pmapping[128];
/**Mapping ON/OFF*/
unsigned char Pmappingenabled;
/**Mapping (keys)*/
short int Pmapping[128];
/**Fine detune to be applied to all notes*/
unsigned char Pglobalfinedetune;
/**Fine detune to be applied to all notes*/
unsigned char Pglobalfinedetune;
// Functions
/** Return the current octave size*/
unsigned char getoctavesize() const;
/**Convert tunning to string*/
void tuningtoline(int n,char *line,int maxn);
/**load the tunnings from a .scl file*/
int loadscl(const char *filename);
/**load the mapping from .kbm file*/
int loadkbm(const char *filename);
/**Load text into the internal tunings
*
*\todo better description*/
int texttotunings(const char *text);
/**Load text into the internal mappings
*
*\todo better description*/
void texttomapping(const char *text);
// Functions
/** Return the current octave size*/
unsigned char getoctavesize() const;
/**Convert tunning to string*/
void tuningtoline(int n, char *line, int maxn);
/**load the tunnings from a .scl file*/
int loadscl(const char *filename);
/**load the mapping from .kbm file*/
int loadkbm(const char *filename);
/**Load text into the internal tunings
*
*\todo better description*/
int texttotunings(const char *text);
/**Load text into the internal mappings
*
*\todo better description*/
void texttomapping(const char *text);
/**Name of Microtonal tuning*/
unsigned char *Pname;
/**Comment about the tuning*/
unsigned char *Pcomment;
/**Name of Microtonal tuning*/
unsigned char *Pname;
/**Comment about the tuning*/
unsigned char *Pcomment;
void add2XML(XMLwrapper *xml)const;
void getfromXML(XMLwrapper *xml);
int saveXML(const char *filename)const;
int loadXML(const char *filename);
void add2XML(XMLwrapper *xml) const;
void getfromXML(XMLwrapper *xml);
int saveXML(const char *filename) const;
int loadXML(const char *filename);
//simple operators primarily for debug
bool operator==(const Microtonal &micro) const;
bool operator!=(const Microtonal &micro) const;
//simple operators primarily for debug
bool operator==(const Microtonal &micro) const;
bool operator!=(const Microtonal &micro) const;
private:
int linetotunings(unsigned int nline,const char *line);
int loadline(FILE *file,char *line);//loads a line from the text file, while ignoring the lines beggining with "!"
unsigned char octavesize;
struct {
unsigned char type;//1 for cents or 2 for division
private:
int linetotunings(unsigned int nline, const char *line);
int loadline(FILE *file, char *line); //loads a line from the text file, while ignoring the lines beggining with "!"
unsigned char octavesize;
struct {
unsigned char type; //1 for cents or 2 for division
// the real tuning (eg. +1.05946 for one halftone)
// or 2.0 for one octave
REALTYPE tuning;
//the real tunning is x1/x2
unsigned int x1,x2;
} octave[MAX_OCTAVE_SIZE],tmpoctave[MAX_OCTAVE_SIZE];
// the real tuning (eg. +1.05946 for one halftone)
// or 2.0 for one octave
REALTYPE tuning;
//the real tunning is x1/x2
unsigned int x1, x2;
} octave[MAX_OCTAVE_SIZE], tmpoctave[MAX_OCTAVE_SIZE];
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -43,159 +43,163 @@
/** Part implementation*/
class Part
{
public:
/**Constructor
* @param microtonal_ Pointer to the microtonal object
* @param fft_ Pointer to the FFTwrapper
* @param mutex_ Pointer to the master pthread_mutex_t*/
Part(Microtonal *microtonal_, FFTwrapper *fft_, pthread_mutex_t *mutex_);
/**Destructor*/
~Part();
public:
/**Constructor
* @param microtonal_ Pointer to the microtonal object
* @param fft_ Pointer to the FFTwrapper
* @param mutex_ Pointer to the master pthread_mutex_t*/
Part(Microtonal *microtonal_,FFTwrapper *fft_,pthread_mutex_t *mutex_);
/**Destructor*/
~Part();
// Midi commands implemented
void NoteOn(unsigned char note,
unsigned char velocity,
int masterkeyshift);
void NoteOff(unsigned char note);
void AllNotesOff(); //panic
void SetController(unsigned int type, int par);
void RelaseSustainedKeys(); //this is called when the sustain pedal is relased
void RelaseAllKeys(); //this is called on AllNotesOff controller
// Midi commands implemented
void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift);
void NoteOff(unsigned char note);
void AllNotesOff();//panic
void SetController(unsigned int type,int par);
void RelaseSustainedKeys();//this is called when the sustain pedal is relased
void RelaseAllKeys();//this is called on AllNotesOff controller
/* The synthesizer part output */
void ComputePartSmps(); //Part output
/* The synthesizer part output */
void ComputePartSmps();//Part output
//instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank)
//instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank)
//saves the instrument settings to a XML file
//returns 0 for ok or <0 if there is an error
int saveXML(char *filename);
int loadXMLinstrument(const char *filename);
//saves the instrument settings to a XML file
//returns 0 for ok or <0 if there is an error
int saveXML(char *filename);
int loadXMLinstrument(const char *filename);
void add2XML(XMLwrapper *xml);
void add2XMLinstrument(XMLwrapper *xml);
void add2XML(XMLwrapper *xml);
void add2XMLinstrument(XMLwrapper *xml);
void defaults();
void defaultsinstrument();
void defaults();
void defaultsinstrument();
void applyparameters();
void applyparameters();
void getfromXML(XMLwrapper *xml);
void getfromXMLinstrument(XMLwrapper *xml);
void getfromXML(XMLwrapper *xml);
void getfromXMLinstrument(XMLwrapper *xml);
void cleanup();
void cleanup();
// ADnoteParameters *ADPartParameters;
// SUBnoteParameters *SUBPartParameters;
//the part's kit
struct {
unsigned char Penabled,Pmuted,Pminkey,Pmaxkey;
unsigned char *Pname;
unsigned char Padenabled,Psubenabled,Ppadenabled;
unsigned char Psendtoparteffect;
ADnoteParameters *adpars;
SUBnoteParameters *subpars;
PADnoteParameters *padpars;
} kit[NUM_KIT_ITEMS];
//Part parameters
void setkeylimit(unsigned char Pkeylimit);
void setkititemstatus(int kititem,int Penabled_);
unsigned char Penabled;/**<if the part is enabled*/
unsigned char Pvolume;/**<part volume*/
unsigned char Pminkey;/**<the minimum key that the part receives noteon messages*/
unsigned char Pmaxkey;//the maximum key that the part receives noteon messages
void setPvolume(char Pvolume);
unsigned char Pkeyshift;//Part keyshift
unsigned char Prcvchn;//from what midi channel it receive commnads
unsigned char Ppanning;//part panning
void setPpanning(char Ppanning);
unsigned char Pvelsns;//velocity sensing (amplitude velocity scale)
unsigned char Pveloffs;//velocity offset
unsigned char Pnoteon;//if the part receives NoteOn messages
unsigned char Pkitmode;//if the kitmode is enabled
unsigned char Pdrummode;//if all keys are mapped and the system is 12tET (used for drums)
unsigned char Ppolymode;//Part mode - 0=monophonic , 1=polyphonic
unsigned char Plegatomode;// 0=normal, 1=legato
unsigned char Pkeylimit;//how many keys are alowed to be played same time (0=off), the older will be relased
unsigned char *Pname; //name of the instrument
struct {//instrument additional information
unsigned char Ptype;
unsigned char Pauthor[MAX_INFO_TEXT_SIZE+1];
unsigned char Pcomments[MAX_INFO_TEXT_SIZE+1];
} info;
REALTYPE *partoutl;//Left channel output of the part
REALTYPE *partoutr;//Right channel output of the part
REALTYPE *partfxinputl[NUM_PART_EFX+1],*partfxinputr[NUM_PART_EFX+1];//Left and right signal that pass thru part effects; partfxinput l/r [NUM_PART_EFX] is for "no effect" buffer
enum NoteStatus {KEY_OFF,KEY_PLAYING,KEY_RELASED_AND_SUSTAINED,KEY_RELASED};
REALTYPE volume,oldvolumel,oldvolumer;//this is applied by Master
REALTYPE panning;//this is applied by Master, too
Controller ctl;//Part controllers
EffectMgr *partefx[NUM_PART_EFX];//insertion part effects (they are part of the instrument)
unsigned char Pefxroute[NUM_PART_EFX];//how the effect's output is routed(to next effect/to out)
bool Pefxbypass[NUM_PART_EFX];//if the effects are bypassed
pthread_mutex_t *mutex;
int lastnote;
private:
void KillNotePos(int pos);
void RelaseNotePos(int pos);
void MonoMemRenote(); // MonoMem stuff.
int killallnotes;//is set to 1 if I want to kill all notes
struct PartNotes {
NoteStatus status;
int note;//if there is no note playing, the "note"=-1
int itemsplaying;
//the part's kit
struct {
ADnote *adnote;
SUBnote *subnote;
PADnote *padnote;
int sendtoparteffect;
} kititem[NUM_KIT_ITEMS];
int time;
};
unsigned char Penabled, Pmuted, Pminkey, Pmaxkey;
unsigned char *Pname;
unsigned char Padenabled, Psubenabled, Ppadenabled;
unsigned char Psendtoparteffect;
ADnoteParameters *adpars;
SUBnoteParameters *subpars;
PADnoteParameters *padpars;
} kit[NUM_KIT_ITEMS];
int lastpos, lastposb; // To keep track of previously used pos and posb.
bool lastlegatomodevalid; // To keep track of previous legatomodevalid.
// MonoMem stuff
std::list<unsigned char> monomemnotes; // A list to remember held notes.
struct {
unsigned char velocity;
int mkeyshift;// I'm not sure masterkeyshift should be remembered.
} monomem[256]; /* 256 is to cover all possible note values.
monomem[] is used in conjunction with the list to
store the velocity and masterkeyshift values of a
given note (the list only store note values).
For example 'monomem[note].velocity' would be the
velocity value of the note 'note'.
*/
//Part parameters
void setkeylimit(unsigned char Pkeylimit);
void setkititemstatus(int kititem, int Penabled_);
PartNotes partnote[POLIPHONY];
unsigned char Penabled; /**<if the part is enabled*/
unsigned char Pvolume; /**<part volume*/
unsigned char Pminkey; /**<the minimum key that the part receives noteon messages*/
unsigned char Pmaxkey; //the maximum key that the part receives noteon messages
void setPvolume(char Pvolume);
unsigned char Pkeyshift; //Part keyshift
unsigned char Prcvchn; //from what midi channel it receive commnads
unsigned char Ppanning; //part panning
void setPpanning(char Ppanning);
unsigned char Pvelsns; //velocity sensing (amplitude velocity scale)
unsigned char Pveloffs; //velocity offset
unsigned char Pnoteon; //if the part receives NoteOn messages
unsigned char Pkitmode; //if the kitmode is enabled
unsigned char Pdrummode; //if all keys are mapped and the system is 12tET (used for drums)
REALTYPE *tmpoutl;//used to get the note
REALTYPE *tmpoutr;
unsigned char Ppolymode; //Part mode - 0=monophonic , 1=polyphonic
unsigned char Plegatomode; // 0=normal, 1=legato
unsigned char Pkeylimit; //how many keys are alowed to be played same time (0=off), the older will be relased
REALTYPE oldfreq;//this is used for portamento
Microtonal *microtonal;
FFTwrapper *fft;
unsigned char *Pname; //name of the instrument
struct { //instrument additional information
unsigned char Ptype;
unsigned char Pauthor[MAX_INFO_TEXT_SIZE + 1];
unsigned char Pcomments[MAX_INFO_TEXT_SIZE + 1];
} info;
REALTYPE *partoutl; //Left channel output of the part
REALTYPE *partoutr; //Right channel output of the part
REALTYPE *partfxinputl[NUM_PART_EFX + 1],
*partfxinputr[NUM_PART_EFX + 1]; //Left and right signal that pass thru part effects; partfxinput l/r [NUM_PART_EFX] is for "no effect" buffer
enum NoteStatus {
KEY_OFF, KEY_PLAYING, KEY_RELASED_AND_SUSTAINED, KEY_RELASED
};
REALTYPE volume, oldvolumel, oldvolumer; //this is applied by Master
REALTYPE panning; //this is applied by Master, too
Controller ctl; //Part controllers
EffectMgr *partefx[NUM_PART_EFX]; //insertion part effects (they are part of the instrument)
unsigned char Pefxroute[NUM_PART_EFX]; //how the effect's output is routed(to next effect/to out)
bool Pefxbypass[NUM_PART_EFX]; //if the effects are bypassed
pthread_mutex_t *mutex;
int lastnote;
private:
void KillNotePos(int pos);
void RelaseNotePos(int pos);
void MonoMemRenote(); // MonoMem stuff.
int killallnotes; //is set to 1 if I want to kill all notes
struct PartNotes {
NoteStatus status;
int note; //if there is no note playing, the "note"=-1
int itemsplaying;
struct {
ADnote *adnote;
SUBnote *subnote;
PADnote *padnote;
int sendtoparteffect;
} kititem[NUM_KIT_ITEMS];
int time;
};
int lastpos, lastposb; // To keep track of previously used pos and posb.
bool lastlegatomodevalid; // To keep track of previous legatomodevalid.
// MonoMem stuff
std::list<unsigned char> monomemnotes; // A list to remember held notes.
struct {
unsigned char velocity;
int mkeyshift; // I'm not sure masterkeyshift should be remembered.
} monomem[256]; /* 256 is to cover all possible note values.
monomem[] is used in conjunction with the list to
store the velocity and masterkeyshift values of a
given note (the list only store note values).
For example 'monomem[note].velocity' would be the
velocity value of the note 'note'.
*/
PartNotes partnote[POLIPHONY];
REALTYPE *tmpoutl; //used to get the note
REALTYPE *tmpoutr;
REALTYPE oldfreq; //this is used for portamento
Microtonal *microtonal;
FFTwrapper *fft;
};
#endif

View File

@@ -19,19 +19,20 @@
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
template <class T>
template<class T>
Stereo<T>::Stereo(const T &left, const T &right)
:leftChannel(left),rightChannel(right)
:leftChannel(left), rightChannel(right)
{}
template <class T>
template<class T>
Stereo<T>::Stereo(const T &val)
:leftChannel(val),rightChannel(val)
:leftChannel(val), rightChannel(val)
{}
template <class T>
void Stereo<T>::operator=(const Stereo<T> & nstr)
template<class T>
void Stereo<T>::operator=(const Stereo<T> &nstr)
{
leftChannel=nstr.leftChannel;
rightChannel=nstr.rightChannel;
leftChannel = nstr.leftChannel;
rightChannel = nstr.rightChannel;
}

View File

@@ -21,46 +21,45 @@
#ifndef STEREO_H
#define STEREO_H
template <class T>
template<class T>
class Stereo
{
public:
Stereo(const T &left,const T &right);
public:
Stereo(const T &left, const T &right);
/**Initializes Stereo with left and right set to val
* @param val the value for both channels*/
Stereo(const T &val);
~Stereo() {};
void operator=(const Stereo<T> &smp);
T &left() {
return leftChannel;
};
T &right() {
return rightChannel;
};
T &l() {
return leftChannel;
};
T &r() {
return rightChannel;
};
const T &left()const {
return leftChannel;
};
const T &right()const {
return rightChannel;
};
const T &l()const {
return leftChannel;
};
const T &r()const {
return rightChannel;
};
private:
T leftChannel;
T rightChannel;
/**Initializes Stereo with left and right set to val
* @param val the value for both channels*/
Stereo(const T &val);
~Stereo() {}
void operator=(const Stereo<T> &smp);
T &left() {
return leftChannel;
}
T &right() {
return rightChannel;
}
T &l() {
return leftChannel;
}
T &r() {
return rightChannel;
}
const T &left() const {
return leftChannel;
}
const T &right() const {
return rightChannel;
}
const T &l() const {
return leftChannel;
}
const T &r() const {
return rightChannel;
}
private:
T leftChannel;
T rightChannel;
};
#include "Stereo.cpp"
#endif

View File

@@ -31,92 +31,85 @@
#include <errno.h>
#include <string.h>
int SAMPLE_RATE=44100;
int SOUND_BUFFER_SIZE=256;
int OSCIL_SIZE=1024;
int SAMPLE_RATE = 44100;
int SOUND_BUFFER_SIZE = 256;
int OSCIL_SIZE = 1024;
Config config;
Config config;
REALTYPE *denormalkillbuf;
/*
* Transform the velocity according the scaling parameter (velocity sensing)
*/
REALTYPE VelF(REALTYPE velocity,unsigned char scaling)
REALTYPE VelF(REALTYPE velocity, unsigned char scaling)
{
REALTYPE x;
x=pow(VELOCITY_MAX_SCALE,(64.0-scaling)/64.0);
if ((scaling==127)||(velocity>0.99)) return(1.0);
else return(pow(velocity,x));
};
x = pow(VELOCITY_MAX_SCALE, (64.0 - scaling) / 64.0);
if((scaling == 127) || (velocity > 0.99))
return 1.0;
else
return pow(velocity, x);
}
/*
* Get the detune in cents
*/
REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune)
REALTYPE getdetune(unsigned char type,
unsigned short int coarsedetune,
unsigned short int finedetune)
{
REALTYPE det=0.0,octdet=0.0,cdet=0.0,findet=0.0;
REALTYPE det = 0.0, octdet = 0.0, cdet = 0.0, findet = 0.0;
//Get Octave
int octave=coarsedetune/1024;
if (octave>=8) octave-=16;
octdet=octave*1200.0;
int octave = coarsedetune / 1024;
if(octave >= 8)
octave -= 16;
octdet = octave * 1200.0;
//Coarse and fine detune
int cdetune=coarsedetune%1024;
if (cdetune>512) cdetune-=1024;
int cdetune = coarsedetune % 1024;
if(cdetune > 512)
cdetune -= 1024;
int fdetune=finedetune-8192;
int fdetune = finedetune - 8192;
switch (type) {
switch(type) {
// case 1: is used for the default (see below)
case 2:
cdet=fabs(cdetune*10.0);
findet=fabs(fdetune/8192.0)*10.0;
cdet = fabs(cdetune * 10.0);
findet = fabs(fdetune / 8192.0) * 10.0;
break;
case 3:
cdet=fabs(cdetune*100);
findet=pow(10,fabs(fdetune/8192.0)*3.0)/10.0-0.1;
cdet = fabs(cdetune * 100);
findet = pow(10, fabs(fdetune / 8192.0) * 3.0) / 10.0 - 0.1;
break;
case 4:
cdet=fabs(cdetune*701.95500087);//perfect fifth
findet=(pow(2,fabs(fdetune/8192.0)*12.0)-1.0)/4095*1200;
cdet = fabs(cdetune * 701.95500087); //perfect fifth
findet = (pow(2, fabs(fdetune / 8192.0) * 12.0) - 1.0) / 4095 * 1200;
break;
//case ...: need to update N_DETUNE_TYPES, if you'll add more
//case ...: need to update N_DETUNE_TYPES, if you'll add more
default:
cdet=fabs(cdetune*50.0);
findet=fabs(fdetune/8192.0)*35.0;//almost like "Paul's Sound Designer 2"
cdet = fabs(cdetune * 50.0);
findet = fabs(fdetune / 8192.0) * 35.0; //almost like "Paul's Sound Designer 2"
break;
};
if (finedetune<8192) findet=-findet;
if (cdetune<0) cdet=-cdet;
}
if(finedetune < 8192)
findet = -findet;
if(cdetune < 0)
cdet = -cdet;
det=octdet+cdet+findet;
return(det);
};
det = octdet + cdet + findet;
return det;
}
bool fileexists(const char *filename)
{
struct stat tmp;
int result=stat(filename,&tmp);
if (result>=0) return(true);
int result = stat(filename, &tmp);
if(result >= 0)
return true;
return(false);
};
void newFFTFREQS(FFTFREQS *f,int size)
{
f->c=new REALTYPE[size];
f->s=new REALTYPE[size];
for (int i=0;i<size;i++) {
f->c[i]=0.0;
f->s[i]=0.0;
};
};
void deleteFFTFREQS(FFTFREQS *f)
{
delete[] f->c;
delete[] f->s;
f->c=f->s=NULL;
};
return false;
}

View File

@@ -23,23 +23,42 @@
#ifndef UTIL_H
#define UTIL_H
#include <pthread.h>
#include <string>
#include <sstream>
#include "../globals.h"
#include "Microtonal.h"
#include "../DSP/FFTwrapper.h"
#include "Config.h"
//Velocity Sensing function
extern REALTYPE VelF(REALTYPE velocity,unsigned char scaling);
extern REALTYPE VelF(REALTYPE velocity, unsigned char scaling);
bool fileexists(const char *filename);
#define N_DETUNE_TYPES 4 //the number of detune types
extern REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune);
extern REALTYPE getdetune(unsigned char type,
unsigned short int coarsedetune,
unsigned short int finedetune);
extern REALTYPE *denormalkillbuf;/**<the buffer to add noise in order to avoid denormalisation*/
extern REALTYPE *denormalkillbuf; /**<the buffer to add noise in order to avoid denormalisation*/
extern Config config;
template<class T>
std::string stringFrom(T x)
{
std::stringstream ss;
ss << x;
return ss.str();
}
template<class T>
T stringTo(const char *x)
{
std::string str = x != NULL ? x : "0"; //should work for the basic float/int
std::stringstream ss(str);
T ans;
ss >> ans;
return ans;
}
#endif

View File

@@ -3,7 +3,9 @@
XMLwrapper.C - XML wrapper
Copyright (C) 2003-2005 Nasca Octavian Paul
Copyright (C) 2009-2009 Mark McCurry
Author: Nasca Octavian Paul
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
@@ -34,241 +36,263 @@
using namespace std;
int xml_k=0;
char tabs[STACKSIZE+2];
int xml_k = 0;
bool verbose = false;
const char *XMLwrapper_whitespace_callback(mxml_node_t *node,int where)
const char *XMLwrapper_whitespace_callback(mxml_node_t *node, int where)
{
const char *name=node->value.element.name;
const char *name = node->value.element.name;
if ((where==MXML_WS_BEFORE_OPEN)&&(!strcmp(name,"?xml"))) return(NULL);
if ((where==MXML_WS_BEFORE_CLOSE)&&(!strcmp(name,"string"))) return(NULL);
if((where == MXML_WS_BEFORE_OPEN) && (!strcmp(name, "?xml")))
return NULL;
if((where == MXML_WS_BEFORE_CLOSE) && (!strcmp(name, "string")))
return NULL;
if ((where==MXML_WS_BEFORE_OPEN)||(where==MXML_WS_BEFORE_CLOSE)) {
if((where == MXML_WS_BEFORE_OPEN) || (where == MXML_WS_BEFORE_CLOSE))
/* const char *tmp=node->value.element.name;
if (tmp!=NULL) {
if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) {
printf("%s ",tmp);
if (where==MXML_WS_BEFORE_OPEN) xml_k++;
if (where==MXML_WS_BEFORE_CLOSE) xml_k--;
if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1;
if (xml_k<0) xml_k=0;
printf("%d\n",xml_k);
printf("\n");
};
if (tmp!=NULL) {
if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) {
printf("%s ",tmp);
if (where==MXML_WS_BEFORE_OPEN) xml_k++;
if (where==MXML_WS_BEFORE_CLOSE) xml_k--;
if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1;
if (xml_k<0) xml_k=0;
printf("%d\n",xml_k);
printf("\n");
};
};
int i=0;
for (i=1;i<xml_k;i++) tabs[i]='\t';
tabs[0]='\n';tabs[i+1]='\0';
if (where==MXML_WS_BEFORE_OPEN) return(tabs);
else return("\n");
};
int i=0;
for (i=1;i<xml_k;i++) tabs[i]='\t';
tabs[0]='\n';tabs[i+1]='\0';
if (where==MXML_WS_BEFORE_OPEN) return(tabs);
else return("\n");
*/
return("\n");
};
return "\n";
;
return(0);
};
return 0;
}
//temporary const overload of mxmlFindElement
const mxml_node_t *mxmlFindElement(const mxml_node_t *node,
const mxml_node_t *top,
const char *name,
const char *attr,
const char *value,
int descend)
{
return const_cast<const mxml_node_t *>(mxmlFindElement(
const_cast<mxml_node_t *>(node),
const_cast<mxml_node_t *>(top),
name, attr, value, descend));
}
//temporary const overload of mxmlElementGetAttr
const char *mxmlElementGetAttr(const mxml_node_t *node, const char *name)
{
return mxmlElementGetAttr(const_cast<mxml_node_t *>(node), name);
}
XMLwrapper::XMLwrapper()
{
ZERO(&parentstack,(int)sizeof(parentstack));
ZERO(&values,(int)sizeof(values));
version.Major = 2;
version.Minor = 4;
version.Revision = 1;
minimal=true;
stackpos=0;
minimal = true;
information.PADsynth_used=false;
tree=mxmlNewElement(MXML_NO_PARENT,"?xml version=\"1.0\" encoding=\"UTF-8\"?");
node = tree = mxmlNewElement(MXML_NO_PARENT,
"?xml version=\"1.0\" encoding=\"UTF-8\"?");
/* for mxml 2.1 (and older)
tree=mxmlNewElement(MXML_NO_PARENT,"?xml");
mxmlElementSetAttr(tree,"version","1.0");
mxmlElementSetAttr(tree,"encoding","UTF-8");
*/
mxml_node_t *doctype=mxmlNewElement(tree,"!DOCTYPE");
mxmlElementSetAttr(doctype,"ZynAddSubFX-data",NULL);
mxml_node_t *doctype = mxmlNewElement(tree, "!DOCTYPE");
mxmlElementSetAttr(doctype, "ZynAddSubFX-data", NULL);
node=root=mxmlNewElement(tree,"ZynAddSubFX-data");
mxmlElementSetAttr(root,"version-major","1");
mxmlElementSetAttr(root,"version-minor","1");
mxmlElementSetAttr(root,"ZynAddSubFX-author","Nasca Octavian Paul");
node = root = addparams("ZynAddSubFX-data", 4,
"version-major", stringFrom<int>(
version.Major).c_str(),
"version-minor", stringFrom<int>(
version.Minor).c_str(),
"version-revision",
stringFrom<int>(version.Revision).c_str(),
"ZynAddSubFX-author", "Nasca Octavian Paul");
//make the empty branch that will contain the information parameters
info=addparams0("INFORMATION");
info = addparams("INFORMATION", 0);
//save zynaddsubfx specifications
beginbranch("BASE_PARAMETERS");
addpar("max_midi_parts",NUM_MIDI_PARTS);
addpar("max_kit_items_per_instrument",NUM_KIT_ITEMS);
addpar("max_midi_parts", NUM_MIDI_PARTS);
addpar("max_kit_items_per_instrument", NUM_KIT_ITEMS);
addpar("max_system_effects",NUM_SYS_EFX);
addpar("max_insertion_effects",NUM_INS_EFX);
addpar("max_instrument_effects",NUM_PART_EFX);
addpar("max_system_effects", NUM_SYS_EFX);
addpar("max_insertion_effects", NUM_INS_EFX);
addpar("max_instrument_effects", NUM_PART_EFX);
addpar("max_addsynth_voices",NUM_VOICES);
addpar("max_addsynth_voices", NUM_VOICES);
endbranch();
};
}
XMLwrapper::~XMLwrapper()
{
if (tree!=NULL) mxmlDelete(tree);
};
if(tree != NULL)
mxmlDelete(tree);
}
bool XMLwrapper::checkfileinformation(const char *filename)
void XMLwrapper::setPadSynth(bool enabled)
{
stackpos=0;
ZERO(&parentstack,(int)sizeof(parentstack));
information.PADsynth_used=false;
/**@bug this might create multiple nodes when only one is needed*/
mxml_node_t *oldnode = node;
node = info;
//Info storing
addparbool("PADsynth_used", enabled);
node = oldnode;
}
if (tree!=NULL) mxmlDelete(tree);
tree=NULL;
char *xmldata=doloadfile(filename);
if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed
bool XMLwrapper::hasPadSynth() const
{
/**Right now this has a copied implementation of setparbool, so this should
* be reworked as XMLwrapper evolves*/
mxml_node_t *tmp = mxmlFindElement(tree,
tree,
"INFORMATION",
NULL,
NULL,
MXML_DESCEND);
mxml_node_t *parameter = mxmlFindElement(tmp,
tmp,
"par_bool",
"name",
"PADsynth_used",
MXML_DESCEND_FIRST);
if(parameter == NULL) //no information availiable
return false;
char *start=strstr(xmldata,"<INFORMATION>");
char *end=strstr(xmldata,"</INFORMATION>");
const char *strval = mxmlElementGetAttr(parameter, "value");
if(strval == NULL) //no information available
return false;
if ((start==NULL)||(end==NULL)||(start>end)) {
delete []xmldata;
return(false);
};
end+=strlen("</INFORMATION>");
end[0]='\0';
tree=mxmlNewElement(MXML_NO_PARENT,"?xml");
node=root=mxmlLoadString(tree,xmldata,MXML_OPAQUE_CALLBACK);
if (root==NULL) {
delete []xmldata;
mxmlDelete(tree);
node=root=tree=NULL;
return(false);
};
root=mxmlFindElement(tree,tree,"INFORMATION",NULL,NULL,MXML_DESCEND);
push(root);
if (root==NULL) {
delete []xmldata;
mxmlDelete(tree);
node=root=tree=NULL;
return(false);
};
information.PADsynth_used=getparbool("PADsynth_used",false);
exitbranch();
if (tree!=NULL) mxmlDelete(tree);
delete []xmldata;
node=root=tree=NULL;
return(true);
};
if((strval[0] == 'Y') || (strval[0] == 'y'))
return true;
else
return false;
}
/* SAVE XML members */
int XMLwrapper::saveXMLfile(const string &filename)
int XMLwrapper::saveXMLfile(const string &filename) const
{
char *xmldata=getXMLdata();
if (xmldata==NULL) return(-2);
char *xmldata = getXMLdata();
if(xmldata == NULL)
return -2;
int compression=config.cfg.GzipCompression;
int result=dosavefile(filename.c_str(),compression,xmldata);
int compression = config.cfg.GzipCompression;
int result = dosavefile(filename.c_str(), compression, xmldata);
free(xmldata);
return(result);
};
return result;
}
char *XMLwrapper::getXMLdata()
char *XMLwrapper::getXMLdata() const
{
xml_k=0;
ZERO(tabs,STACKSIZE+2);
xml_k = 0;
mxml_node_t *oldnode=node;
char *xmldata = mxmlSaveAllocString(tree, XMLwrapper_whitespace_callback);
node=info;
//Info storing
addparbool("PADsynth_used",information.PADsynth_used);
node=oldnode;
char *xmldata=mxmlSaveAllocString(tree,XMLwrapper_whitespace_callback);
return(xmldata);
};
return xmldata;
}
int XMLwrapper::dosavefile(const char *filename,int compression,const char *xmldata)
int XMLwrapper::dosavefile(const char *filename,
int compression,
const char *xmldata) const
{
if (compression==0) {
if(compression == 0) {
FILE *file;
file=fopen(filename,"w");
if (file==NULL) return(-1);
fputs(xmldata,file);
file = fopen(filename, "w");
if(file == NULL)
return -1;
fputs(xmldata, file);
fclose(file);
} else {
if (compression>9) compression=9;
if (compression<1) compression=1;
}
else {
if(compression > 9)
compression = 9;
if(compression < 1)
compression = 1;
char options[10];
snprintf(options,10,"wb%d",compression);
snprintf(options, 10, "wb%d", compression);
gzFile gzfile;
gzfile=gzopen(filename,options);
if (gzfile==NULL) return(-1);
gzputs(gzfile,xmldata);
gzfile = gzopen(filename, options);
if(gzfile == NULL)
return -1;
gzputs(gzfile, xmldata);
gzclose(gzfile);
};
}
return(0);
};
return 0;
}
void XMLwrapper::addpar(const string &name,int val)
void XMLwrapper::addpar(const string &name, int val)
{
addparams2("par","name",name.c_str(),"value",int2str(val));
};
addparams("par", 2, "name", name.c_str(), "value", stringFrom<int>(
val).c_str());
}
void XMLwrapper::addparreal(const string &name,REALTYPE val)
void XMLwrapper::addparreal(const string &name, REALTYPE val)
{
addparams2("par_real","name",name.c_str(),"value",real2str(val));
};
addparams("par_real", 2, "name", name.c_str(), "value",
stringFrom<REALTYPE>(val).c_str());
}
void XMLwrapper::addparbool(const string &name,int val)
void XMLwrapper::addparbool(const string &name, int val)
{
if (val!=0) addparams2("par_bool","name",name.c_str(),"value","yes");
else addparams2("par_bool","name",name.c_str(),"value","no");
};
if(val != 0)
addparams("par_bool", 2, "name", name.c_str(), "value", "yes");
else
addparams("par_bool", 2, "name", name.c_str(), "value", "no");
}
void XMLwrapper::addparstr(const string &name,const string &val)
void XMLwrapper::addparstr(const string &name, const string &val)
{
mxml_node_t *element=mxmlNewElement(node,"string");
mxmlElementSetAttr(element,"name",name.c_str());
mxmlNewText(element,0,val.c_str());
};
mxml_node_t *element = mxmlNewElement(node, "string");
mxmlElementSetAttr(element, "name", name.c_str());
mxmlNewText(element, 0, val.c_str());
}
void XMLwrapper::beginbranch(const string &name)
{
push(node);
node=addparams0(name.c_str());
};
if(verbose)
cout << "beginbranch()" << name << endl;
node = addparams(name.c_str(), 0);
}
void XMLwrapper::beginbranch(const string &name,int id)
void XMLwrapper::beginbranch(const string &name, int id)
{
push(node);
node=addparams1(name.c_str(),"id",int2str(id));
};
if(verbose)
cout << "beginbranch(" << id << ")" << name << endl;
node = addparams(name.c_str(), 1, "id", stringFrom<int>(id).c_str());
}
void XMLwrapper::endbranch()
{
node=pop();
};
if(verbose)
cout << "endbranch()" << node << "-" << node->value.element.name
<< " To "
<< node->parent << "-" << node->parent->value.element.name << endl;
node = node->parent;
}
@@ -276,61 +300,71 @@ void XMLwrapper::endbranch()
int XMLwrapper::loadXMLfile(const string &filename)
{
if (tree!=NULL) mxmlDelete(tree);
tree=NULL;
if(tree != NULL)
mxmlDelete(tree);
tree = NULL;
ZERO(&parentstack,(int)sizeof(parentstack));
ZERO(&values,(int)sizeof(values));
const char *xmldata = doloadfile(filename.c_str());
if(xmldata == NULL)
return -1; //the file could not be loaded or uncompressed
stackpos=0;
root = tree = mxmlLoadString(NULL, xmldata, MXML_OPAQUE_CALLBACK);
const char *xmldata=doloadfile(filename.c_str());
if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed
delete [] xmldata;
root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK);
delete []xmldata;
if (tree==NULL) return(-2);//this is not XML
if(tree == NULL)
return -2; //this is not XML
node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND);
if (root==NULL) return(-3);//the XML doesnt embbed zynaddsubfx data
push(root);
node = root = mxmlFindElement(tree,
tree,
"ZynAddSubFX-data",
NULL,
NULL,
MXML_DESCEND);
if(root == NULL)
return -3; //the XML doesnt embbed zynaddsubfx data
values.xml_version.major=str2int(mxmlElementGetAttr(root,"version-major"));
values.xml_version.minor=str2int(mxmlElementGetAttr(root,"version-minor"));
//fetch version information
version.Major = stringTo<int>(mxmlElementGetAttr(root, "version-major"));
version.Minor = stringTo<int>(mxmlElementGetAttr(root, "version-minor"));
version.Revision =
stringTo<int>(mxmlElementGetAttr(root, "version-revision"));
return(0);
};
if(verbose)
cout << "loadXMLfile() version: " << version.Major << '.'
<< version.Minor << '.' << version.Revision << endl;
char *XMLwrapper::doloadfile(const string &filename)
return 0;
}
char *XMLwrapper::doloadfile(const string &filename) const
{
char * xmldata = NULL;
gzFile gzfile = gzopen(filename.c_str(),"rb");
if (gzfile != NULL) {//The possibly compressed file opened
char *xmldata = NULL;
gzFile gzfile = gzopen(filename.c_str(), "rb");
if(gzfile != NULL) { //The possibly compressed file opened
stringstream strBuf; //reading stream
const int bufSize = 500; //fetch size
char fetchBuf[bufSize+1];//fetch buffer
int read = 0; //chars read in last fetch
char fetchBuf[bufSize + 1]; //fetch buffer
int read = 0; //chars read in last fetch
fetchBuf[bufSize] = 0;//force null termination
fetchBuf[bufSize] = 0; //force null termination
while(bufSize == (read = gzread(gzfile, fetchBuf, bufSize)))
strBuf << fetchBuf;
fetchBuf[read] = 0;//Truncate last partial read
fetchBuf[read] = 0; //Truncate last partial read
strBuf << fetchBuf;
gzclose(gzfile);
//Place data in output format
string tmp = strBuf.str();
xmldata = new char[tmp.size()+1];
strncpy(xmldata, tmp.c_str(), tmp.size()+1);
xmldata = new char[tmp.size() + 1];
strncpy(xmldata, tmp.c_str(), tmp.size() + 1);
}
return xmldata;
@@ -338,218 +372,246 @@ char *XMLwrapper::doloadfile(const string &filename)
bool XMLwrapper::putXMLdata(const char *xmldata)
{
if (tree!=NULL) mxmlDelete(tree);
tree=NULL;
if(tree != NULL)
mxmlDelete(tree);
ZERO(&parentstack,(int)sizeof(parentstack));
ZERO(&values,(int)sizeof(values));
tree = NULL;
if(xmldata == NULL)
return false;
stackpos=0;
root = tree = mxmlLoadString(NULL, xmldata, MXML_OPAQUE_CALLBACK);
if(tree == NULL)
return false;
if (xmldata==NULL) return (false);
node = root = mxmlFindElement(tree,
tree,
"ZynAddSubFX-data",
NULL,
NULL,
MXML_DESCEND);
if(root == NULL)
return false;
root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK);
if (tree==NULL) return(false);
node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND);
if (root==NULL) return (false);;
push(root);
return(true);
};
return true;
}
int XMLwrapper::enterbranch(const string &name)
{
node=mxmlFindElement(peek(),peek(),name.c_str(),NULL,NULL,MXML_DESCEND_FIRST);
if (node==NULL) return(0);
if(verbose)
cout << "enterbranch() " << name << endl;
mxml_node_t *tmp = mxmlFindElement(node, node,
name.c_str(), NULL, NULL,
MXML_DESCEND_FIRST);
if(tmp == NULL)
return 0;
push(node);
return(1);
};
node = tmp;
return 1;
}
int XMLwrapper::enterbranch(const string &name,int id)
int XMLwrapper::enterbranch(const string &name, int id)
{
snprintf(tmpstr,TMPSTR_SIZE,"%d",id);
node=mxmlFindElement(peek(),peek(),name.c_str(),"id",tmpstr,MXML_DESCEND_FIRST);
if (node==NULL) return(0);
if(verbose)
cout << "enterbranch(" << id << ") " << name << endl;
mxml_node_t *tmp = mxmlFindElement(node, node,
name.c_str(), "id", stringFrom<int>(
id).c_str(), MXML_DESCEND_FIRST);
if(tmp == NULL)
return 0;
push(node);
return(1);
};
node = tmp;
return 1;
}
void XMLwrapper::exitbranch()
{
/**@bug Does not set the current node correctly*/
pop();
};
if(verbose)
cout << "exitbranch()" << node << "-" << node->value.element.name
<< " To "
<< node->parent << "-" << node->parent->value.element.name << endl;
node = node->parent;
}
int XMLwrapper::getbranchid(int min, int max)
int XMLwrapper::getbranchid(int min, int max) const
{
int id=str2int(mxmlElementGetAttr(node,"id"));
if ((min==0)&&(max==0)) return(id);
int id = stringTo<int>(mxmlElementGetAttr(node, "id"));
if((min == 0) && (max == 0))
return id;
if (id<min) id=min;
else if (id>max) id=max;
if(id < min)
id = min;
else
if(id > max)
id = max;
return(id);
};
return id;
}
int XMLwrapper::getpar(const string &name,int defaultpar,int min,int max)
int XMLwrapper::getpar(const string &name, int defaultpar, int min,
int max) const
{
node=mxmlFindElement(peek(),peek(),"par","name",name.c_str(),MXML_DESCEND_FIRST);
if (node==NULL) return(defaultpar);
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"par",
"name",
name.c_str(),
MXML_DESCEND_FIRST);
const char *strval=mxmlElementGetAttr(node,"value");
if (strval==NULL) return(defaultpar);
if(tmp == NULL)
return defaultpar;
int val=str2int(strval);
if (val<min) val=min;
else if (val>max) val=max;
const char *strval = mxmlElementGetAttr(tmp, "value");
if(strval == NULL)
return defaultpar;
return(val);
};
int val = stringTo<int>(strval);
if(val < min)
val = min;
else
if(val > max)
val = max;
int XMLwrapper::getpar127(const string &name,int defaultpar)
return val;
}
int XMLwrapper::getpar127(const string &name, int defaultpar) const
{
return(getpar(name,defaultpar,0,127));
};
return getpar(name, defaultpar, 0, 127);
}
int XMLwrapper::getparbool(const string &name,int defaultpar)
int XMLwrapper::getparbool(const string &name, int defaultpar) const
{
node=mxmlFindElement(peek(),peek(),"par_bool","name",name.c_str(),MXML_DESCEND_FIRST);
if (node==NULL) return(defaultpar);
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"par_bool",
"name",
name.c_str(),
MXML_DESCEND_FIRST);
const char *strval=mxmlElementGetAttr(node,"value");
if (strval==NULL) return(defaultpar);
if(tmp == NULL)
return defaultpar;
if ((strval[0]=='Y')||(strval[0]=='y')) return(1);
else return(0);
};
const char *strval = mxmlElementGetAttr(tmp, "value");
if(strval == NULL)
return defaultpar;
void XMLwrapper::getparstr(const string &name,char *par,int maxstrlen)
if((strval[0] == 'Y') || (strval[0] == 'y'))
return 1;
else
return 0;
}
void XMLwrapper::getparstr(const string &name, char *par, int maxstrlen) const
{
ZERO(par,maxstrlen);
node=mxmlFindElement(peek(),peek(),"string","name",name.c_str(),MXML_DESCEND_FIRST);
ZERO(par, maxstrlen);
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"string",
"name",
name.c_str(),
MXML_DESCEND_FIRST);
if (node==NULL) return;
if (node->child==NULL) return;
if (node->child->type!=MXML_OPAQUE) return;
if(tmp == NULL)
return;
if(tmp->child == NULL)
return;
if(tmp->child->type == MXML_OPAQUE) {
snprintf(par, maxstrlen, "%s", tmp->child->value.element.name);
return;
}
if((tmp->child->type == MXML_TEXT)
&& (tmp->child->value.text.string != NULL)) {
snprintf(par, maxstrlen, "%s", tmp->child->value.text.string);
return;
}
}
snprintf(par,maxstrlen,"%s",node->child->value.element.name);
};
REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar)
string XMLwrapper::getparstr(const string &name,
const std::string &defaultpar) const
{
node=mxmlFindElement(peek(),peek(),"par_real","name",name,MXML_DESCEND_FIRST);
if (node==NULL) return(defaultpar);
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"string",
"name",
name.c_str(),
MXML_DESCEND_FIRST);
const char *strval=mxmlElementGetAttr(node,"value");
if (strval==NULL) return(defaultpar);
if((tmp == NULL) || (tmp->child == NULL))
return defaultpar;
return(str2real(strval));
};
if((tmp->child->type == MXML_OPAQUE)
&& (tmp->child->value.element.name != NULL))
return tmp->child->value.element.name;
REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max)
if((tmp->child->type == MXML_TEXT)
&& (tmp->child->value.text.string != NULL))
return tmp->child->value.text.string;
return defaultpar;
}
REALTYPE XMLwrapper::getparreal(const char *name, REALTYPE defaultpar) const
{
REALTYPE result=getparreal(name,defaultpar);
const mxml_node_t *tmp = mxmlFindElement(node,
node,
"par_real",
"name",
name,
MXML_DESCEND_FIRST);
if(tmp == NULL)
return defaultpar;
if (result<min) result=min;
else if (result>max) result=max;
return(result);
};
const char *strval = mxmlElementGetAttr(tmp, "value");
if(strval == NULL)
return defaultpar;
return stringTo<REALTYPE>(strval);
}
REALTYPE XMLwrapper::getparreal(const char *name,
REALTYPE defaultpar,
REALTYPE min,
REALTYPE max) const
{
REALTYPE result = getparreal(name, defaultpar);
if(result < min)
result = min;
else
if(result > max)
result = max;
return result;
}
/** Private members **/
char *XMLwrapper::int2str(int x)
mxml_node_t *XMLwrapper::addparams(const char *name, unsigned int params,
...) const
{
snprintf(tmpstr,TMPSTR_SIZE,"%d",x);
return(tmpstr);
};
char *XMLwrapper::real2str(REALTYPE x)
{
snprintf(tmpstr,TMPSTR_SIZE,"%g",x);
return(tmpstr);
};
int XMLwrapper::str2int(const char *str)
{
if (str==NULL) return(0);
int result=strtol(str,NULL,10);
return(result);
};
REALTYPE XMLwrapper::str2real(const char *str)
{
if (str==NULL) return(0.0);
REALTYPE result=strtod(str,NULL);
return(result);
};
mxml_node_t *XMLwrapper::addparams0(const char *name)
{
mxml_node_t *element=mxmlNewElement(node,name);
return(element);
};
mxml_node_t *XMLwrapper::addparams1(const char *name,const char *par1,const char *val1)
{
mxml_node_t *element=mxmlNewElement(node,name);
mxmlElementSetAttr(element,par1,val1);
return(element);
};
mxml_node_t *XMLwrapper::addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2)
{
mxml_node_t *element=mxmlNewElement(node,name);
mxmlElementSetAttr(element,par1,val1);
mxmlElementSetAttr(element,par2,val2);
return(element);
};
void XMLwrapper::push(mxml_node_t *node)
{
if (stackpos>=STACKSIZE-1) {
cerr << "BUG!: XMLwrapper::push() - full parentstack" << endl;
return;
};
stackpos++;
parentstack[stackpos]=node;
// printf("push %d - %s\n",stackpos,node->value.element.name);
};
mxml_node_t *XMLwrapper::pop()
{
if (stackpos<=0) {
cerr << "BUG!: XMLwrapper::pop() - empty parentstack" << endl;
return (root);
};
mxml_node_t *node=parentstack[stackpos];
parentstack[stackpos]=NULL;
// printf("pop %d - %s\n",stackpos,node->value.element.name);
stackpos--;
return(node);
};
mxml_node_t *XMLwrapper::peek()
{
if (stackpos<=0) {
cerr << "BUG!: XMLwrapper::peek() - empty parentstack" << endl;
return (root);
};
return(parentstack[stackpos]);
};
/**@todo make this function send out a good error message if something goes
* wrong**/
mxml_node_t *element = mxmlNewElement(node, name);
if(params) {
va_list variableList;
va_start(variableList, params);
const char *ParamName;
const char *ParamValue;
while(params--) {
ParamName = va_arg(variableList, const char *);
ParamValue = va_arg(variableList, const char *);
if(verbose)
cout << "addparams()[" << params << "]=" << name << " "
<< ParamName << "=\"" << ParamValue << "\"" << endl;
mxmlElementSetAttr(element, ParamName, ParamValue);
}
}
return element;
}

View File

@@ -31,287 +31,242 @@
#ifndef XML_WRAPPER_H
#define XML_WRAPPER_H
#define TMPSTR_SIZE 50
//the maxim tree depth
#define STACKSIZE 100
/**Mxml wrapper*/
class XMLwrapper
{
public:
/**
* Constructor.
* Will Construct the object and fill in top level branch
* */
XMLwrapper();
public:
/**
* Constructor.
* Will Construct the object and fill in top level branch
* */
XMLwrapper();
/**Destructor*/
~XMLwrapper();
/**Destructor*/
~XMLwrapper();
/**
* Saves the XML to a file.
* @param filename the name of the destination file.
* @returns 0 if ok or -1 if the file cannot be saved.
*/
int saveXMLfile(const std::string &filename);
/**
* Saves the XML to a file.
* @param filename the name of the destination file.
* @returns 0 if ok or -1 if the file cannot be saved.
*/
int saveXMLfile(const std::string &filename) const;
/**
* Return XML tree as a string.
* Note: The string must be freed with free() to deallocate
* @returns a newly allocated NULL terminated string of the XML data.
*/
char *getXMLdata();
/**
* Return XML tree as a string.
* Note: The string must be freed with free() to deallocate
* @returns a newly allocated NULL terminated string of the XML data.
*/
char *getXMLdata() const;
/**
* Add simple parameter.
* @param name The name of the mXML node.
* @param val The string value of the mXml node
*/
void addpar(const std::string &name,int val);
/**
* Add simple parameter.
* @param name The name of the mXML node.
* @param val The string value of the mXml node
*/
void addpar(const std::string &name, int val);
/**
* Adds a realtype parameter.
* @param name The name of the mXML node.
* @param val The REALTYPE value of the node.
*/
void addparreal(const std::string &name,REALTYPE val);
/**
* Adds a realtype parameter.
* @param name The name of the mXML node.
* @param val The REALTYPE value of the node.
*/
void addparreal(const std::string &name, REALTYPE val);
/**
* Add boolean parameter.
* \todo Fix this reverse boolean logic.
* @param name The name of the mXML node.
* @param val The boolean value of the node (0->"yes";else->"no").
*/
void addparbool(const std::string &name,int val);
/**
* Add boolean parameter.
* \todo Fix this reverse boolean logic.
* @param name The name of the mXML node.
* @param val The boolean value of the node (0->"yes";else->"no").
*/
void addparbool(const std::string &name, int val);
/**
* Add string parameter.
* @param name The name of the mXML node.
* @param val The string value of the node.
*/
void addparstr(const std::string &name,const std::string &val);
/**
* Add string parameter.
* @param name The name of the mXML node.
* @param val The string value of the node.
*/
void addparstr(const std::string &name, const std::string &val);
/**
* Create a new branch.
* @param name Name of new branch
* @see void endbranch()
*/
void beginbranch(const std::string &name);
/**
* Create a new branch.
* @param name Name of new branch
* @param id "id" value of branch
* @see void endbranch()
*/
void beginbranch(const std::string &name, int id);
/**
* Create a new branch.
* @param name Name of new branch
* @see void endbranch()
*/
void beginbranch(const std::string &name);
/**
* Create a new branch.
* @param name Name of new branch
* @param id "id" value of branch
* @see void endbranch()
*/
void beginbranch(const std::string &name, int id);
/**Closes new branches.
* This must be called to exit each branch created by beginbranch( ).
* @see void beginbranch(const std::string &name)
* @see void beginbranch(const std::string &name, int id)
*/
void endbranch();
/**Closes new branches.
* This must be called to exit each branch created by beginbranch( ).
* @see void beginbranch(const std::string &name)
* @see void beginbranch(const std::string &name, int id)
*/
void endbranch();
/**
* Loads file into XMLwrapper.
* @param filename file to be loaded
* @returns 0 if ok or -1 if the file cannot be loaded
*/
int loadXMLfile(const std::string &filename);
/**
* Loads file into XMLwrapper.
* @param filename file to be loaded
* @returns 0 if ok or -1 if the file cannot be loaded
*/
int loadXMLfile(const std::string &filename);
/**
* Loads string into XMLwrapper.
* @param xmldata NULL terminated string of XML data.
* @returns true if successful.
*/
bool putXMLdata(const char *xmldata);
/**
* Loads string into XMLwrapper.
* @param xmldata NULL terminated string of XML data.
* @returns true if successful.
*/
bool putXMLdata(const char *xmldata);
/**
* Enters the branch.
* @param name Name of branch.
* @returns 1 if is ok, or 0 otherwise.
*/
int enterbranch(const std::string &name);
/**
* Enters the branch.
* @param name Name of branch.
* @returns 1 if is ok, or 0 otherwise.
*/
int enterbranch(const std::string &name);
/**
* Enter into the branch \c name with id \c id.
* @param name Name of branch.
* @param id Value of branch's "id".
* @returns 1 if is ok, or 0 otherwise.
*/
int enterbranch(const std::string &name, int id);
/**
* Enter into the branch \c name with id \c id.
* @param name Name of branch.
* @param id Value of branch's "id".
* @returns 1 if is ok, or 0 otherwise.
*/
int enterbranch(const std::string &name, int id);
/**Exits from a branch*/
void exitbranch();
/**Exits from a branch*/
void exitbranch();
/**Get the the branch_id and limits it between the min and max.
* if min==max==0, it will not limit it
* if there isn't any id, will return min
* this must be called only imediately after enterbranch()
*/
int getbranchid(int min, int max);
/**Get the the branch_id and limits it between the min and max.
* if min==max==0, it will not limit it
* if there isn't any id, will return min
* this must be called only imediately after enterbranch()
*/
int getbranchid(int min, int max) const;
/**
* Returns the integer value stored in node name.
* It returns the integer value between the limits min and max.
* If min==max==0, then the value will not be limited.
* If there is no location named name, then defaultpar will be returned.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
* @param min The minimum return value.
* @param max The maximum return value.
*/
int getpar(const std::string &name,int defaultpar,int min,int max);
/**
* Returns the integer value stored in node name.
* It returns the integer value between the limits min and max.
* If min==max==0, then the value will not be limited.
* If there is no location named name, then defaultpar will be returned.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
* @param min The minimum return value.
* @param max The maximum return value.
*/
int getpar(const std::string &name, int defaultpar, int min,
int max) const;
/**
* Returns the integer value stored in the node with range [0,127].
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
*/
int getpar127(const std::string &name,int defaultpar);
/**
* Returns the integer value stored in the node with range [0,127].
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
*/
int getpar127(const std::string &name, int defaultpar) const;
/**
* Returns the boolean value stored in the node.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
*/
int getparbool(const std::string &name,int defaultpar);
/**
* Returns the boolean value stored in the node.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
*/
int getparbool(const std::string &name, int defaultpar) const;
/**
* Get the string value stored in the node.
* @param name The parameter name.
* @param par Pointer to destination string
* @param maxstrlen Max string length for destination
*/
void getparstr(const std::string &name,char *par,int maxstrlen);
/**
* Get the string value stored in the node.
* @param name The parameter name.
* @param par Pointer to destination string
* @param maxstrlen Max string length for destination
*/
void getparstr(const std::string &name, char *par, int maxstrlen) const;
/**
* Returns the real value stored in the node.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
*/
REALTYPE getparreal(const char *name,REALTYPE defaultpar);
/**
* Get the string value stored in the node.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
*/
std::string getparstr(const std::string &name,
const std::string &defaultpar) const;
/**
* Returns the real value stored in the node.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
* @param min The minimum value
* @param max The maximum value
*/
REALTYPE getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max);
/**
* Returns the real value stored in the node.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
*/
REALTYPE getparreal(const char *name, REALTYPE defaultpar) const;
bool minimal;/**<false if all parameters will be stored (used only for clipboard)*/
/**
* Returns the real value stored in the node.
* @param name The parameter name.
* @param defaultpar The default value if the real value is not found.
* @param min The minimum value
* @param max The maximum value
*/
REALTYPE getparreal(const char *name,
REALTYPE defaultpar,
REALTYPE min,
REALTYPE max) const;
struct {
bool PADsynth_used;/**<if PADsynth is used*/
}information;/**<Defines if PADsynth is used*/
bool minimal; /**<false if all parameters will be stored (used only for clipboard)*/
/**
* Opens a file and parses the "information" section data on it.
* @returns "true" if all went ok or "false" on errors.
*/
bool checkfileinformation(const char *filename);
/**
* Sets the current tree's PAD Synth usage
*/
void setPadSynth(bool enabled);
/**
* Checks the current tree for PADsynth usage
*/
bool hasPadSynth() const;
private:
private:
/**
* Save the file.
* @param filename File to save to
* @param compression Level of gzip compression
* @param xmldata String to be saved
*/
int dosavefile(const char *filename,int compression,const char *xmldata);
/**
* Save the file.
* @param filename File to save to
* @param compression Level of gzip compression
* @param xmldata String to be saved
*/
int dosavefile(const char *filename,
int compression,
const char *xmldata) const;
/**
* Loads specified file and returns data.
*
* Will load a gziped file or an uncompressed file.
* @param filename the file
* @return The decompressed data
*/
char *doloadfile(const std::string &filename);
/**
* Loads specified file and returns data.
*
* Will load a gziped file or an uncompressed file.
* @param filename the file
* @return The decompressed data
*/
char *doloadfile(const std::string &filename) const;
mxml_node_t *tree; /**<all xml data*/
mxml_node_t *root; /**<xml data used by zynaddsubfx*/
mxml_node_t *node; /**<current subtree in parsing or writing */
mxml_node_t *info; /**<Node used to store the information about the data*/
mxml_node_t *tree;/**<all xml data*/
mxml_node_t *root;/**<xml data used by zynaddsubfx*/
mxml_node_t *node;/**<current node*/
mxml_node_t *info;/**<Node used to store the information about the data*/
/**
* Create mxml_node_t with specified name and parameters
*
* Results should look like:
* <name optionalParam1="value1" optionalParam2="value2" ...>
*
* @param name The name of the xml node
* @param params The number of the attributes
* @param ... const char * pairs that are in the format attribute_name,
* attribute_value
*/
mxml_node_t *addparams(const char *name, unsigned int params,
...) const;
/**
* Adds params like this:
* <name>.
* @returns The node
*/
mxml_node_t *addparams0(const char *name);
/**
* Adds params like this:
* <name par1="val1">.
* @returns The node
*/
mxml_node_t *addparams1(const char *name,const char *par1,const char *val1);
/**
* Adds params like this:
* <name par1="val1" par2="val2">.
* @returns the node
*/
mxml_node_t *addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2);
/**
* Convert integer to string
* @param x integer input
* @returns string output
*/
char *int2str(int x);
/**
* Convert integer to string
* @param x integer input
* @returns string output
*/
char *real2str(REALTYPE x);
/**
* Convert string to int
* @param str string input
* @returns integer output
*/
int str2int(const char *str);
/**
* Convert string to realtype
* @param x integer input
* @returns string output
*/
REALTYPE str2real(const char *str);
/**Temporary string for various uses*/
char tmpstr[TMPSTR_SIZE];
/**this is used to store the parents.
* @todo Use the stack class provided by C++*/
mxml_node_t *parentstack[STACKSIZE];
int stackpos;/**<position in stack*/
void push(mxml_node_t *node);
/**Pops top node off of parent stack*/
mxml_node_t *pop();
/**Returns top node off of parent stack*/
mxml_node_t *peek();
struct {
/**@todo keep these numbers up to date*/
struct {
int major;/**<major version number.*/
int minor;/**<minor version number.*/
}xml_version;/**<Stores ZynAddSubFX versioning information*/
}values;/**< Stores ZynAddSubFX versioning information*/
int Major; /**<major version number.*/
int Minor; /**<minor version number.*/
int Revision; /**<version revision number.*/
} version;
};
#endif

View File

@@ -27,7 +27,7 @@
#include "DSSIaudiooutput.h"
static LADSPA_Descriptor *tsLDescriptor = NULL;
static DSSI_Descriptor *tsDDescriptor = NULL;
static DSSI_Descriptor *tsDDescriptor = NULL;
typedef struct {
LADSPA_Data *outl;
@@ -42,11 +42,11 @@ static void cleanupTS(LADSPA_Handle instance)
free(instance);
}
static void connectPortTS(LADSPA_Handle instance, unsigned long port,
LADSPA_Data * data)
LADSPA_Data *data)
{
TS *plugin;
plugin = (TS *) instance;
switch (port) {
switch(port) {
case 0:
plugin->outl = data;
break;
@@ -58,7 +58,7 @@ static void connectPortTS(LADSPA_Handle instance, unsigned long port,
const LADSPA_Descriptor *ladspa_descriptor(unsigned long index)
{
switch (index) {
switch(index) {
case 0:
return tsLDescriptor;
default:
@@ -71,7 +71,7 @@ const DSSI_Descriptor *dssi_descriptor(unsigned long index)
// FILE *a=fopen("/tmp/zzzzz11z","w");
// fprintf(a,"aaaaaaaaaaa TEST\n");
// fclose(a);
switch (index) {
switch(index) {
case 0:
return tsDDescriptor;
default:
@@ -79,14 +79,13 @@ const DSSI_Descriptor *dssi_descriptor(unsigned long index)
}
}
static LADSPA_Handle instantiateTS(const LADSPA_Descriptor * descriptor,
static LADSPA_Handle instantiateTS(const LADSPA_Descriptor *descriptor,
unsigned long s_rate)
{
TS *plugin_data = (TS *) malloc(sizeof(TS));
/* for (i=0; i<MIDI_NOTES; i++) {
plugin_data->omega[i] = M_PI * 2.0 / (double)s_rate *
pow(2.0, (i-69.0) / 12.0);
plugin_data->omega[i] = M_PI * 2.0 / (double)s_rate *
pow(2.0, (i-69.0) / 12.0);
}
*/
return (LADSPA_Handle) plugin_data;
@@ -115,47 +114,47 @@ static void runTS(LADSPA_Handle instance, unsigned long sample_count,
unsigned long note;
/* if (freq < 1.0) {
freq = 440.0f;
freq = 440.0f;
}
if (vol < 0.000001) {
vol = 1.0f;
vol = 1.0f;
}
if (event_count > 0) {
printf("trivial_synth: have %ld events\n", event_count);
printf("trivial_synth: have %ld events\n", event_count);
}
for (pos = 0, event_pos = 0; pos < sample_count; pos++) {
while (event_pos < event_count
&& pos == events[event_pos].time.tick) {
while (event_pos < event_count
&& pos == events[event_pos].time.tick) {
printf("trivial_synth: event type %d\n", events[event_pos].type);
printf("trivial_synth: event type %d\n", events[event_pos].type);
if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) {
data[events[event_pos].data.note.note].amp =
events[event_pos].data.note.velocity / 512.0f;
data[events[event_pos].data.note.note].
active = events[event_pos].data.note.velocity > 0;
data[events[event_pos].data.note.note].
phase = 0.0;
} else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF) {
data[events[event_pos].data.note.note].
active = 0;
}
event_pos++;
}
if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) {
data[events[event_pos].data.note.note].amp =
events[event_pos].data.note.velocity / 512.0f;
data[events[event_pos].data.note.note].
active = events[event_pos].data.note.velocity > 0;
data[events[event_pos].data.note.note].
phase = 0.0;
} else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF) {
data[events[event_pos].data.note.note].
active = 0;
}
event_pos++;
}
output[pos] = 0.0f;
for (note = 0; note < MIDI_NOTES; note++) {
if (data[note].active) {
output[pos] += sin(data[note].phase) * data[note].amp * vol;
data[note].phase += plugin_data->omega[note] * freq;
if (data[note].phase > M_PI * 2.0) {
data[note].phase -= M_PI * 2.0;
}
}
}
output[pos] = 0.0f;
for (note = 0; note < MIDI_NOTES; note++) {
if (data[note].active) {
output[pos] += sin(data[note].phase) * data[note].amp * vol;
data[note].phase += plugin_data->omega[note] * freq;
if (data[note].phase > M_PI * 2.0) {
data[note].phase -= M_PI * 2.0;
}
}
}
}
*/
}
@@ -176,22 +175,23 @@ void _init()
{
char **port_names;
LADSPA_PortDescriptor *port_descriptors;
LADSPA_PortRangeHint *port_range_hints;
LADSPA_PortRangeHint *port_range_hints;
FILE *a=fopen("/tmp/zzzzzz","w");
fprintf(a,"aaaaaaaaaaa TEST\n");
FILE *a = fopen("/tmp/zzzzzz", "w");
fprintf(a, "aaaaaaaaaaa TEST\n");
fclose(a);
tsLDescriptor = (LADSPA_Descriptor *) malloc(sizeof(LADSPA_Descriptor));
if (tsLDescriptor) {
tsLDescriptor->UniqueID = 100;
tsLDescriptor->Label = "ZASF";
if(tsLDescriptor) {
tsLDescriptor->UniqueID = 100;
tsLDescriptor->Label = "ZASF";
tsLDescriptor->Properties = 0;
tsLDescriptor->Name = "ZynAddSubFX";
tsLDescriptor->Maker = "Nasca Octavian Paul <zynaddsubfx@yahoo.com>";
tsLDescriptor->Copyright = "GNU General Public License v.2";
tsLDescriptor->PortCount = 2;
tsLDescriptor->Maker =
"Nasca Octavian Paul <zynaddsubfx@yahoo.com>";
tsLDescriptor->Copyright = "GNU General Public License v.2";
tsLDescriptor->PortCount = 2;
port_descriptors = (LADSPA_PortDescriptor *)
calloc(tsLDescriptor->PortCount, sizeof
@@ -208,42 +208,40 @@ void _init()
port_names = (char **) calloc(tsLDescriptor->PortCount, sizeof(char *));
tsLDescriptor->PortNames = (const char **) port_names;
port_descriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_descriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_names[0] = "Output L";
port_range_hints[0].HintDescriptor = 0;
port_descriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_names[1] = "Output R";
port_range_hints[1].HintDescriptor = 0;
tsLDescriptor->activate = activateTS;
tsLDescriptor->cleanup = cleanupTS;
tsLDescriptor->activate = activateTS;
tsLDescriptor->cleanup = cleanupTS;
tsLDescriptor->connect_port = connectPortTS;
tsLDescriptor->deactivate = NULL;
tsLDescriptor->instantiate = instantiateTS;
tsLDescriptor->deactivate = NULL;
tsLDescriptor->instantiate = instantiateTS;
tsLDescriptor->run = runTSWrapper;
tsLDescriptor->run_adding = NULL;
tsLDescriptor->run_adding = NULL;
tsLDescriptor->set_run_adding_gain = NULL;
}
tsDDescriptor = (DSSI_Descriptor *) malloc(sizeof(DSSI_Descriptor));
if (tsDDescriptor) {
tsDDescriptor->DSSI_API_Version = 1;
tsDDescriptor->LADSPA_Plugin = tsLDescriptor;
if(tsDDescriptor) {
tsDDescriptor->DSSI_API_Version = 1;
tsDDescriptor->LADSPA_Plugin = tsLDescriptor;
tsDDescriptor->configure = NULL;
tsDDescriptor->get_program = NULL;
tsDDescriptor->get_program = NULL;
tsDDescriptor->get_midi_controller_for_port = getControllerTS;
tsDDescriptor->select_program = NULL;
tsDDescriptor->select_program = NULL;
tsDDescriptor->run_synth = runTS;
tsDDescriptor->run_synth_adding = NULL;
tsDDescriptor->run_synth_adding = NULL;
tsDDescriptor->run_multiple_synths = NULL;
tsDDescriptor->run_multiple_synths_adding = NULL;
}
};
}
void _fini()
{
};
{}
@@ -272,17 +270,18 @@ long int VSTSynth::canDo(char *txt){
};
bool VSTSynth::getVendorString(char *txt){
strcpy(txt,"Nasca O. Paul");
return(true);
strcpy(txt,"Nasca O. Paul");
return(true);
};
bool VSTSynth::getProductString(char *txt){
strcpy(txt,"ZynAddSubFX");
return(true);
strcpy(txt,"ZynAddSubFX");
return(true);
};
void VSTSynth::resume(){
wantEvents();
wantEvents();
};
*/

View File

@@ -34,25 +34,25 @@
/*
class VSTSynth:public AudioEffectX{
public:
VSTSynth (audioMasterCallback audioMaster);
~VSTSynth();
VSTSynth (audioMasterCallback audioMaster);
~VSTSynth();
virtual void process (float **inputs, float **outputs, long sampleframes);
virtual void processReplacing (float **inputs, float **outputs, long sampleframes);
virtual long processEvents(VstEvents *events);//this is used for Midi input
virtual long int canDo(char *txt);
virtual bool getVendorString(char *txt);
virtual bool getProductString(char *txt);
virtual void resume();
virtual void process (float **inputs, float **outputs, long sampleframes);
virtual void processReplacing (float **inputs, float **outputs, long sampleframes);
virtual long processEvents(VstEvents *events);//this is used for Midi input
virtual long int canDo(char *txt);
virtual bool getVendorString(char *txt);
virtual bool getProductString(char *txt);
virtual void resume();
virtual long getChunk(void** data,bool isPreset=false);
virtual void setChunk(void *data,long size,bool isPreset=false);
virtual long getChunk(void** data,bool isPreset=false);
virtual void setChunk(void *data,long size,bool isPreset=false);
MasterUI *ui;
int Pexitprogram;
MasterUI *ui;
int Pexitprogram;
Master *vmaster;
pthread_t thr;
pthread_t thr;
};
*/
#endif

View File

@@ -33,174 +33,197 @@ extern "C"
#include "JACKaudiooutput.h"
Master *jackmaster;
jack_client_t *jackclient;
jack_port_t *outport_left,*outport_right;
jack_ringbuffer_t *rb=NULL;
jack_client_t *jackclient;
jack_port_t *outport_left, *outport_right;
jack_ringbuffer_t *rb = NULL;
REALTYPE *jackoutl,*jackoutr;
int jackfinish=0;
REALTYPE *jackoutl, *jackoutr;
int jackfinish = 0;
void *thread_blocked(void *arg);
int jackprocess(jack_nframes_t nframes,void *arg);
int jacksrate(jack_nframes_t nframes,void *arg);
int jackprocess(jack_nframes_t nframes, void *arg);
int jacksrate(jack_nframes_t nframes, void *arg);
void jackshutdown(void *arg);
pthread_cond_t more_data=PTHREAD_COND_INITIALIZER;
pthread_mutex_t zyn_thread_lock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t more_data = PTHREAD_COND_INITIALIZER;
pthread_mutex_t zyn_thread_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_t bthr;
bool JACKaudiooutputinit(Master *master_)
{
jackmaster=master_;
jackclient=0;
jackmaster = master_;
jackclient = 0;
char tmpstr[100];
jackoutl=new REALTYPE [SOUND_BUFFER_SIZE];
jackoutr=new REALTYPE [SOUND_BUFFER_SIZE];
jackoutl = new REALTYPE [SOUND_BUFFER_SIZE];
jackoutr = new REALTYPE [SOUND_BUFFER_SIZE];
int rbbufsize=SOUND_BUFFER_SIZE*sizeof (REALTYPE)*2*2;
printf("%d\n",rbbufsize);
rb=jack_ringbuffer_create(rbbufsize);
for (int i=0;i<rbbufsize;i++) rb->buf[i]=0.0;
int rbbufsize = SOUND_BUFFER_SIZE * sizeof(REALTYPE) * 2 * 2;
printf("%d\n", rbbufsize);
rb = jack_ringbuffer_create(rbbufsize);
for(int i = 0; i < rbbufsize; i++)
rb->buf[i] = 0.0;
for (int i=0;i<15;i++) {
if (i!=0) snprintf(tmpstr,100,"ZynAddSubFX_%d",i);
else snprintf(tmpstr,100,"ZynAddSubFX");
jackclient=jack_client_new(tmpstr);
if (jackclient!=0) break;
};
for(int i = 0; i < 15; i++) {
if(i != 0)
snprintf(tmpstr, 100, "ZynAddSubFX_%d", i);
else
snprintf(tmpstr, 100, "ZynAddSubFX");
jackclient = jack_client_new(tmpstr);
if(jackclient != 0)
break;
}
if (jackclient==0) {
fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n");
return(false);
};
if(jackclient == 0) {
fprintf(
stderr,
"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n");
return false;
}
fprintf(stderr,"Internal SampleRate = %d\nJack Output SampleRate= %d\n",SAMPLE_RATE,jack_get_sample_rate(jackclient));
if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE)
fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n");
fprintf(stderr,
"Internal SampleRate = %d\nJack Output SampleRate= %d\n",
SAMPLE_RATE,
jack_get_sample_rate(jackclient));
if((unsigned int)jack_get_sample_rate(jackclient) !=
(unsigned int) SAMPLE_RATE)
fprintf(stderr,
"It is recomanded that the both samplerates to be equal.\n");
jack_set_process_callback(jackclient,jackprocess,0);
jack_set_sample_rate_callback(jackclient,jacksrate,0);
jack_on_shutdown(jackclient,jackshutdown,0);
jack_set_process_callback(jackclient, jackprocess, 0);
jack_set_sample_rate_callback(jackclient, jacksrate, 0);
jack_on_shutdown(jackclient, jackshutdown, 0);
outport_left=jack_port_register(jackclient,"out_1",
JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0);
outport_right=jack_port_register(jackclient,"out_2",
JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0);
outport_left = jack_port_register(jackclient,
"out_1",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput | JackPortIsTerminal,
0);
outport_right = jack_port_register(jackclient,
"out_2",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput | JackPortIsTerminal,
0);
if (jack_activate(jackclient)) {
fprintf(stderr,"Cannot activate jack client\n");
return(false);
};
if(jack_activate(jackclient)) {
fprintf(stderr, "Cannot activate jack client\n");
return false;
}
pthread_create(&bthr,NULL,thread_blocked,NULL);
pthread_create(&bthr, NULL, thread_blocked, NULL);
/*
jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1");
jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2");
*/
return(true);
};
return true;
}
void *thread_blocked(void *arg)
{
int datasize=SOUND_BUFFER_SIZE*sizeof (REALTYPE);
int datasize = SOUND_BUFFER_SIZE * sizeof(REALTYPE);
//try to get realtime
sched_param sc;
sc.sched_priority=50;
int err=sched_setscheduler(0,SCHED_FIFO,&sc);
sc.sched_priority = 50;
int err = sched_setscheduler(0, SCHED_FIFO, &sc);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_mutex_lock(&zyn_thread_lock);
while (jackfinish==0) {
while (jack_ringbuffer_write_space(rb)>=datasize) {
while(jackfinish == 0) {
while(jack_ringbuffer_write_space(rb) >= datasize) {
pthread_mutex_lock(&jackmaster->mutex);
jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,jack_get_sample_rate(jackclient),jackoutl,jackoutr);
jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,
jack_get_sample_rate(jackclient),
jackoutl,
jackoutr);
pthread_mutex_unlock(&jackmaster->mutex);
jack_ringbuffer_write(rb, (char *) jackoutl,datasize);
jack_ringbuffer_write(rb, (char *) jackoutr,datasize);
};
pthread_cond_wait(&more_data,&zyn_thread_lock);
};
jack_ringbuffer_write(rb, (char *) jackoutl, datasize);
jack_ringbuffer_write(rb, (char *) jackoutr, datasize);
}
pthread_cond_wait(&more_data, &zyn_thread_lock);
}
pthread_mutex_unlock(&zyn_thread_lock);
return(0);
};
return 0;
}
int jackprocess(jack_nframes_t nframes,void *arg)
int jackprocess(jack_nframes_t nframes, void *arg)
{
jack_default_audio_sample_t *outl=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_left, nframes);
jack_default_audio_sample_t *outr=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_right, nframes);
jack_default_audio_sample_t *outl =
(jack_default_audio_sample_t *) jack_port_get_buffer(outport_left,
nframes);
jack_default_audio_sample_t *outr =
(jack_default_audio_sample_t *) jack_port_get_buffer(outport_right,
nframes);
int datasize=nframes*sizeof (REALTYPE);
int incoming_datasize=SOUND_BUFFER_SIZE*sizeof (REALTYPE);
int data_read=0;
int datasize = nframes * sizeof(REALTYPE);
int incoming_datasize = SOUND_BUFFER_SIZE * sizeof(REALTYPE);
int data_read = 0;
if (jack_ringbuffer_read_space(rb)>=(2*incoming_datasize)) {
if (datasize>incoming_datasize) {
data_read=0;
while (data_read < datasize) {
jack_ringbuffer_read(rb, (char *) outl+data_read,datasize);
jack_ringbuffer_read(rb, (char *) outr+data_read,datasize);
data_read+=incoming_datasize;
};
} else if (datasize==incoming_datasize) {
jack_ringbuffer_read(rb, (char *) outl,datasize);
jack_ringbuffer_read(rb, (char *) outr,datasize);
} else {
};
} else {//the ringbuffer is empty or there are too small amount of samples in it
for (int i=0;i<nframes;i++) {
outl[i]=0.0;
outr[i]=0.0;
};
};
if(jack_ringbuffer_read_space(rb) >= (2 * incoming_datasize)) {
if(datasize > incoming_datasize) {
data_read = 0;
while(data_read < datasize) {
jack_ringbuffer_read(rb, (char *) outl + data_read, datasize);
jack_ringbuffer_read(rb, (char *) outr + data_read, datasize);
data_read += incoming_datasize;
}
}
else
if(datasize == incoming_datasize) {
jack_ringbuffer_read(rb, (char *) outl, datasize);
jack_ringbuffer_read(rb, (char *) outr, datasize);
}
else {}
}
else { //the ringbuffer is empty or there are too small amount of samples in it
for(int i = 0; i < nframes; i++) {
outl[i] = 0.0;
outr[i] = 0.0;
}
}
/* if (jack_ringbuffer_read_space(rb)>=datasize){
jack_ringbuffer_read(rb, (char *) outl,datasize);
jack_ringbuffer_read(rb, (char *) outr,datasize);
jack_ringbuffer_read(rb, (char *) outl,datasize);
jack_ringbuffer_read(rb, (char *) outr,datasize);
} else {//the ringbuffer is empty or there are too small amount of samples in it
for (int i=0;i<nframes;i++){
outl[i]=0.0;outr[i]=0.0;
};
for (int i=0;i<nframes;i++){
outl[i]=0.0;outr[i]=0.0;
};
};
*/
if (pthread_mutex_trylock(&zyn_thread_lock)==0) {
if(pthread_mutex_trylock(&zyn_thread_lock) == 0) {
pthread_cond_signal(&more_data);
pthread_mutex_unlock(&zyn_thread_lock);
};
}
return(0);
};
return 0;
}
void JACKfinish()
{
jackfinish=1;
jackfinish = 1;
jack_ringbuffer_free(rb);
jack_client_close(jackclient);
usleep(100000);
delete(jackoutl);
delete(jackoutr);
};
delete (jackoutl);
delete (jackoutr);
}
int jacksrate(jack_nframes_t nframes,void *arg)
int jacksrate(jack_nframes_t nframes, void *arg)
{
return(0);
};
return 0;
}
void jackshutdown(void *arg)
{
};
{}

View File

@@ -27,110 +27,132 @@
Master *jackmaster;
jack_client_t *jackclient;
char jackname[100];
jack_port_t *outport_left,*outport_right,*midi_inport;
jack_port_t *outport_left, *outport_right, *midi_inport;
int jackprocess(jack_nframes_t nframes,void *arg);
int jacksrate(jack_nframes_t nframes,void *arg);
int jackprocess(jack_nframes_t nframes, void *arg);
int jacksrate(jack_nframes_t nframes, void *arg);
void jackshutdown(void *arg);
bool JACKaudiooutputinit(Master *master_)
{
jackmaster=master_;
jackclient=0;
jackmaster = master_;
jackclient = 0;
for (int i=0;i<15;i++) {
if (i!=0) snprintf(jackname,100,"ZynAddSubFX_%d",i);
else snprintf(jackname,100,"ZynAddSubFX");
jackclient=jack_client_new(jackname);
if (jackclient!=0) break;
};
for(int i = 0; i < 15; i++) {
if(i != 0)
snprintf(jackname, 100, "ZynAddSubFX_%d", i);
else
snprintf(jackname, 100, "ZynAddSubFX");
jackclient = jack_client_new(jackname);
if(jackclient != 0)
break;
}
if (jackclient==0) {
fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n");
return(false);
};
if(jackclient == 0) {
fprintf(
stderr,
"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n");
return false;
}
fprintf(stderr,"Internal SampleRate = %d\nJack Output SampleRate= %d\n",SAMPLE_RATE,jack_get_sample_rate(jackclient));
if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE)
fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n");
fprintf(stderr,
"Internal SampleRate = %d\nJack Output SampleRate= %d\n",
SAMPLE_RATE,
jack_get_sample_rate(jackclient));
if((unsigned int)jack_get_sample_rate(jackclient) !=
(unsigned int) SAMPLE_RATE)
fprintf(stderr,
"It is recomanded that the both samplerates to be equal.\n");
jack_set_process_callback(jackclient,jackprocess,0);
jack_set_sample_rate_callback(jackclient,jacksrate,0);
jack_on_shutdown(jackclient,jackshutdown,0);
jack_set_process_callback(jackclient, jackprocess, 0);
jack_set_sample_rate_callback(jackclient, jacksrate, 0);
jack_on_shutdown(jackclient, jackshutdown, 0);
outport_left=jack_port_register(jackclient,"out_1",
JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0);
outport_right=jack_port_register(jackclient,"out_2",
JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0);
midi_inport=jack_port_register(jackclient,"midi_input",
JACK_DEFAULT_MIDI_TYPE,JackPortIsInput|JackPortIsTerminal,0);
outport_left = jack_port_register(jackclient,
"out_1",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput | JackPortIsTerminal,
0);
outport_right = jack_port_register(jackclient,
"out_2",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput | JackPortIsTerminal,
0);
midi_inport = jack_port_register(jackclient,
"midi_input",
JACK_DEFAULT_MIDI_TYPE,
JackPortIsInput | JackPortIsTerminal,
0);
if (jack_activate(jackclient)) {
fprintf(stderr,"Cannot activate jack client\n");
return(false);
};
if(jack_activate(jackclient)) {
fprintf(stderr, "Cannot activate jack client\n");
return false;
}
/*
jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1");
jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2");
*/
return(true);
};
return true;
}
int jackprocess(jack_nframes_t nframes,void *arg)
int jackprocess(jack_nframes_t nframes, void *arg)
{
jack_default_audio_sample_t *outl=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_left, nframes);
jack_default_audio_sample_t *outr=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_right, nframes);
jack_default_audio_sample_t *outl =
(jack_default_audio_sample_t *) jack_port_get_buffer(outport_left,
nframes);
jack_default_audio_sample_t *outr =
(jack_default_audio_sample_t *) jack_port_get_buffer(outport_right,
nframes);
if (!pthread_mutex_trylock(&jackmaster->mutex)) {
if(!pthread_mutex_trylock(&jackmaster->mutex)) {
JACKhandlemidi(nframes);
jackmaster->GetAudioOutSamples(nframes,jack_get_sample_rate(jackclient),outl,outr);
jackmaster->GetAudioOutSamples(nframes, jack_get_sample_rate(
jackclient), outl, outr);
pthread_mutex_unlock(&jackmaster->mutex);
} else {
}
else {
memset(outl, 0, sizeof(jack_default_audio_sample_t) * nframes);
memset(outr, 0, sizeof(jack_default_audio_sample_t) * nframes);
}
return(0);
};
return 0;
}
void JACKfinish()
{
jack_client_close(jackclient);
};
}
int jacksrate(jack_nframes_t nframes,void *arg)
int jacksrate(jack_nframes_t nframes, void *arg)
{
return(0);
};
return 0;
}
void jackshutdown(void *arg)
{
};
{}
void JACKhandlemidi(unsigned long frames)
{
// We must have the master mutex before we run this function
// XXX This is really nasty, not only do we lose the sample accuracy of
// JACK MIDI, but any accuracy at all below the buffer size
void* midi_buf = jack_port_get_buffer(midi_inport, frames);
void *midi_buf = jack_port_get_buffer(midi_inport, frames);
jack_midi_event_t jack_midi_event;
jack_nframes_t event_index = 0;
unsigned char* midi_data;
unsigned char type, chan;
jack_nframes_t event_index = 0;
unsigned char *midi_data;
unsigned char type, chan;
while (jack_midi_event_get(&jack_midi_event,midi_buf, event_index++) == 0) {
while(jack_midi_event_get(&jack_midi_event, midi_buf,
event_index++) == 0) {
midi_data = jack_midi_event.buffer;
type = midi_data[0] & 0xF0;
chan = midi_data[0] & 0x0F;
switch (type) {
type = midi_data[0] & 0xF0;
chan = midi_data[0] & 0x0F;
switch(type) {
case 0x80: /* note-off */
jackmaster->NoteOff(chan, midi_data[1]);
break;
@@ -151,13 +173,13 @@ void JACKhandlemidi(unsigned long frames)
/* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */
}
}
}
const char* JACKgetname()
const char *JACKgetname()
{
if (jackclient != NULL)
if(jackclient != NULL)
return jackname;
return NULL;
}

View File

@@ -28,11 +28,12 @@
#include "../Misc/Master.h"
#if (REALTYPE!=jack_default_audio_sample_t)
#error "The internal sample datatype of ZynAddSubFX and the datatype of jack differs.\
In order to compile ZynAddSubFX the 'REALTYPE' and 'jack_default_audio_sample_t' must be equal.\
Set the 'REALTYPE' data type (which is defined in 'globals.h') to what is defined \
in the file types.h from jack include directory as 'jack_default_audio_sample_t' (as float or double)."
#if (REALTYPE != jack_default_audio_sample_t)
#error \
"The internal sample datatype of ZynAddSubFX and the datatype of jack differs. \
In order to compile ZynAddSubFX the 'REALTYPE' and 'jack_default_audio_sample_t' must be equal. \
Set the 'REALTYPE' data type (which is defined in 'globals.h') to what is defined \
in the file types.h from jack include directory as 'jack_default_audio_sample_t' (as float or double)."
#endif
@@ -41,7 +42,7 @@
bool JACKaudiooutputinit(Master *master_);
void JACKfinish();
void JACKhandlemidi(unsigned long frames);
const char* JACKgetname();
const char *JACKgetname();
#endif

View File

@@ -37,60 +37,92 @@ using namespace std;
OSSaudiooutput::OSSaudiooutput()
{
int i;
int snd_bitsize=16;
snd_fragment=0x00080009;//fragment size (?)
snd_stereo=1;//stereo
snd_format=AFMT_S16_LE;
snd_samplerate=SAMPLE_RATE;
int snd_bitsize = 16;
snd_fragment = 0x00080009; //fragment size (?)
snd_stereo = 1; //stereo
snd_format = AFMT_S16_LE;
snd_samplerate = SAMPLE_RATE;
playing_until.tv_sec = 0;
playing_until.tv_usec = 0;
smps=new short int[SOUND_BUFFER_SIZE*2];
for (i=0;i<SOUND_BUFFER_SIZE*2;i++) smps[i]=0;
smps = new short int[SOUND_BUFFER_SIZE * 2];
for(i = 0; i < SOUND_BUFFER_SIZE * 2; i++)
smps[i] = 0;
snd_handle=open(config.cfg.LinuxOSSWaveOutDev,O_WRONLY,0);
if (snd_handle == -1) {
snd_handle = open(config.cfg.LinuxOSSWaveOutDev, O_WRONLY, 0);
if(snd_handle == -1) {
cerr << "ERROR - I can't open the ";
cerr << config.cfg.LinuxOSSWaveOutDev << '.'<< endl;
cerr << config.cfg.LinuxOSSWaveOutDev << '.' << endl;
return;
};
ioctl(snd_handle,SNDCTL_DSP_RESET,NULL);
}
ioctl(snd_handle, SNDCTL_DSP_RESET, NULL);
ioctl(snd_handle,SNDCTL_DSP_SETFMT,&snd_format);
ioctl(snd_handle,SNDCTL_DSP_STEREO,&snd_stereo);
ioctl(snd_handle,SNDCTL_DSP_SPEED,&snd_samplerate);
ioctl(snd_handle,SNDCTL_DSP_SAMPLESIZE,&snd_bitsize);
ioctl(snd_handle,SNDCTL_DSP_SETFRAGMENT,&snd_fragment);
};
ioctl(snd_handle, SNDCTL_DSP_SETFMT, &snd_format);
ioctl(snd_handle, SNDCTL_DSP_STEREO, &snd_stereo);
ioctl(snd_handle, SNDCTL_DSP_SPEED, &snd_samplerate);
ioctl(snd_handle, SNDCTL_DSP_SAMPLESIZE, &snd_bitsize);
ioctl(snd_handle, SNDCTL_DSP_SETFRAGMENT, &snd_fragment);
}
/*
* Output the samples to the soundcard
* The samples are bigger than -1.0 and smaller 1.0
*/
void OSSaudiooutput::OSSout(REALTYPE *smp_left,REALTYPE *smp_right)
void OSSaudiooutput::OSSout(REALTYPE *smp_left, REALTYPE *smp_right)
{
int i;
REALTYPE l,r;
if (snd_handle<0) return;
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
l=smp_left[i];
r=smp_right[i];
int i;
REALTYPE l, r;
if(snd_handle < 0) { //output could not be opened
struct timeval now;
int remaining;
gettimeofday(&now, NULL);
if((playing_until.tv_usec == 0) && (playing_until.tv_sec == 0)) {
playing_until.tv_usec = now.tv_usec;
playing_until.tv_sec = now.tv_sec;
}
else {
remaining = (playing_until.tv_usec - now.tv_usec)
+ (playing_until.tv_sec - now.tv_sec) * 1000000;
if(remaining > 10000) //Don't sleep() less than 10ms.
//This will add latency...
usleep(remaining - 10000);
if(remaining < 0)
cerr << "WARNING - too late" << endl;
}
playing_until.tv_usec += SOUND_BUFFER_SIZE * 1000000 / SAMPLE_RATE;
if(remaining < 0)
playing_until.tv_usec -= remaining;
playing_until.tv_sec += playing_until.tv_usec / 1000000;
playing_until.tv_usec %= 1000000;
return;
}
if (l<-1.0) l=-1.0;
else if (l>1.0) l=1.0;
if (r<-1.0) r=-1.0;
else if (r>1.0) r=1.0;
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
l = smp_left[i];
r = smp_right[i];
smps[i*2]=(short int) (l*32767.0);
smps[i*2+1]=(short int) (r*32767.0);
};
write(snd_handle,smps,SOUND_BUFFER_SIZE*4);// *2 because is 16 bit, again * 2 because is stereo
};
if(l < -1.0)
l = -1.0;
else
if(l > 1.0)
l = 1.0;
if(r < -1.0)
r = -1.0;
else
if(r > 1.0)
r = 1.0;
smps[i * 2] = (short int) (l * 32767.0);
smps[i * 2 + 1] = (short int) (r * 32767.0);
}
write(snd_handle, smps, SOUND_BUFFER_SIZE * 4); // *2 because is 16 bit, again * 2 because is stereo
}
OSSaudiooutput::~OSSaudiooutput()
{
close(snd_handle);
delete [] smps;
};
}

View File

@@ -23,25 +23,27 @@
#ifndef OSS_AUDIO_OUTPUT_H
#define OSS_AUDIO_OUTPUT_H
#include <sys/time.h>
#include "../globals.h"
class OSSaudiooutput
{
public:
OSSaudiooutput();
~OSSaudiooutput();
public:
OSSaudiooutput();
~OSSaudiooutput();
//the out is [-1.0 .. 1.0]
/* smp_left[] and smp_right[] has the size of SOUND_BUFFER_SIZE */
void OSSout(REALTYPE *smp_left,REALTYPE *smp_right);
private:
int snd_handle;
int snd_fragment;
int snd_stereo;
int snd_format;
int snd_samplerate;
//the out is [-1.0 .. 1.0]
/* smp_left[] and smp_right[] has the size of SOUND_BUFFER_SIZE */
void OSSout(REALTYPE *smp_left, REALTYPE *smp_right);
private:
int snd_handle;
int snd_fragment;
int snd_stereo;
int snd_format;
int snd_samplerate;
struct timeval playing_until;
short int *smps;//Samples to be sent to soundcard
short int *smps; //Samples to be sent to soundcard
};
#endif

View File

@@ -22,52 +22,59 @@
#include "PAaudiooutput.h"
Master *PAmaster;
Master *PAmaster;
PaStream *stream;
REALTYPE *outl,*outr;
REALTYPE *outl, *outr;
int PAprocess(void *inputBuffer,void *outputBuffer,
int PAprocess(void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
PaTimestamp outTime,void *userData)
PaTimestamp outTime, void *userData)
{
if (framesPerBuffer!=SOUND_BUFFER_SIZE) {
fprintf(stderr,"Bug: PAudioOutput::PAprocess SOUND_BUFFER_SIZE!=framesPerBuffer");
fprintf(stderr,"%d %d\n",framesPerBuffer,SOUND_BUFFER_SIZE);
};
if(framesPerBuffer != SOUND_BUFFER_SIZE) {
fprintf(
stderr,
"Bug: PAudioOutput::PAprocess SOUND_BUFFER_SIZE!=framesPerBuffer");
fprintf(stderr, "%d %d\n", framesPerBuffer, SOUND_BUFFER_SIZE);
}
pthread_mutex_lock(&PAmaster->mutex);
PAmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,SAMPLE_RATE,outl,outr);
PAmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE, SAMPLE_RATE, outl, outr);
pthread_mutex_unlock(&PAmaster->mutex);
float *out=(float *)outputBuffer;
float *out = (float *)outputBuffer;
for (int i=0;i<framesPerBuffer;i++) {
if (i>=SOUND_BUFFER_SIZE) break;//this should never happens, except only when framesPerBuffer!>SOUND_BUFFER_SIZE
out[i*2]=outl[i];
out[i*2+1]=outr[i];
};
for(int i = 0; i < framesPerBuffer; i++) {
if(i >= SOUND_BUFFER_SIZE)
break; //this should never happens, except only when framesPerBuffer!>SOUND_BUFFER_SIZE
out[i * 2] = outl[i];
out[i * 2 + 1] = outr[i];
}
return(0);
};
return 0;
}
void PAaudiooutputinit(Master *master_)
{
PAmaster=master_;
outl=new REALTYPE [SOUND_BUFFER_SIZE];
outr=new REALTYPE [SOUND_BUFFER_SIZE];
PAmaster = master_;
outl = new REALTYPE [SOUND_BUFFER_SIZE];
outr = new REALTYPE [SOUND_BUFFER_SIZE];
Pa_Initialize();
Pa_OpenDefaultStream(&stream,0,2,paFloat32,SAMPLE_RATE,SOUND_BUFFER_SIZE,0,PAprocess,NULL);
Pa_OpenDefaultStream(&stream,
0,
2,
paFloat32,
SAMPLE_RATE,
SOUND_BUFFER_SIZE,
0,
PAprocess,
NULL);
Pa_StartStream(stream);
};
}
void PAfinish()
{
Pa_StopStream(stream);
delete (outl);
delete (outr);
};
}

View File

@@ -25,80 +25,89 @@
Recorder::Recorder()
{
recordbuf_16bit=new short int [SOUND_BUFFER_SIZE*2];
status=0;
notetrigger=0;
for (int i=0;i<SOUND_BUFFER_SIZE*2;i++) {
recordbuf_16bit[i]=0;
}
};
recordbuf_16bit = new short int [SOUND_BUFFER_SIZE * 2];
status = 0;
notetrigger = 0;
for(int i = 0; i < SOUND_BUFFER_SIZE * 2; i++)
recordbuf_16bit[i] = 0;
}
Recorder::~Recorder()
{
if (recording()==1) stop();
if(recording() == 1)
stop();
delete [] recordbuf_16bit;
};
}
int Recorder::preparefile(std::string filename_,int overwrite)
int Recorder::preparefile(std::string filename_, int overwrite)
{
if (!overwrite) {
if(!overwrite) {
struct stat fileinfo;
int statr;
statr = stat(filename_.c_str(),&fileinfo);
if (statr == 0) {//file exists
statr = stat(filename_.c_str(), &fileinfo);
if(statr == 0) //file exists
return 1;
}
}
if (!wav.newfile(filename_, SAMPLE_RATE,2)) return 2;
if(!wav.newfile(filename_, SAMPLE_RATE, 2))
return 2;
status=1;//ready
status = 1; //ready
return(0);
};
return 0;
}
void Recorder::start()
{
notetrigger=0;
status=2;//recording
};
notetrigger = 0;
status = 2; //recording
}
void Recorder::stop()
{
wav.close();
status=0;
};
status = 0;
}
void Recorder::pause()
{
status=0;
};
status = 0;
}
int Recorder::recording()
{
if ((status==2)&&(notetrigger!=0)) return(1);
else return(0);
};
if((status == 2) && (notetrigger != 0))
return 1;
else
return 0;
}
void Recorder::recordbuffer(REALTYPE *outl,REALTYPE *outr)
void Recorder::recordbuffer(REALTYPE *outl, REALTYPE *outr)
{
int tmp;
if (status!=2) return;
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
tmp=(int)(outl[i]*32767.0);
if (tmp<-32768) tmp=-32768;
if (tmp>32767) tmp=32767;
recordbuf_16bit[i*2]=tmp;
if(status != 2)
return;
for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
tmp = (int)(outl[i] * 32767.0);
if(tmp < -32768)
tmp = -32768;
if(tmp > 32767)
tmp = 32767;
recordbuf_16bit[i * 2] = tmp;
tmp=(int)(outr[i]*32767.0);
if (tmp<-32768) tmp=-32768;
if (tmp>32767) tmp=32767;
recordbuf_16bit[i*2+1]=tmp;
};
wav.write_stereo_samples(SOUND_BUFFER_SIZE,recordbuf_16bit);
};
tmp = (int)(outr[i] * 32767.0);
if(tmp < -32768)
tmp = -32768;
if(tmp > 32767)
tmp = 32767;
recordbuf_16bit[i * 2 + 1] = tmp;
}
wav.write_stereo_samples(SOUND_BUFFER_SIZE, recordbuf_16bit);
}
void Recorder::triggernow()
{
if (status==2) notetrigger=1;
};
if(status == 2)
notetrigger = 1;
}

View File

@@ -29,28 +29,29 @@
/**Records sound to a file*/
class Recorder
{
public:
public:
Recorder();
~Recorder();
int preparefile(std::string filename_,int overwrite);//returns 1 if the file exists
void start();
void stop();
void pause();
int recording();
void triggernow();
void recordbuffer(REALTYPE *outl,REALTYPE *outr);
Recorder();
~Recorder();
int preparefile(std::string filename_, int overwrite); //returns 1 if the file exists
void start();
void stop();
void pause();
int recording();
void triggernow();
void recordbuffer(REALTYPE *outl, REALTYPE *outr);
/** Status:
* 0 - not ready(no file selected),
* 1 - ready
* 2 - recording */
int status;
/** Status:
* 0 - not ready(no file selected),
* 1 - ready
* 2 - recording */
int status;
private:
WAVaudiooutput wav;
short int *recordbuf_16bit;
int notetrigger;
private:
WAVaudiooutput wav;
short int *recordbuf_16bit;
int notetrigger;
};
#endif

View File

@@ -24,42 +24,45 @@
//the constructor and the destructor are defined in main.C
void VSTSynth::process (float **inputs, float **outputs, long sampleframes)
void VSTSynth::process(float **inputs, float **outputs, long sampleframes)
{
float *outl=outputs[0];
float *outr=outputs[1];
float *outl = outputs[0];
float *outr = outputs[1];
pthread_mutex_lock(&vmaster->mutex);
vmaster->GetAudioOutSamples(sampleframes,(int) getSampleRate(),outl,outr);
vmaster->GetAudioOutSamples(sampleframes, (int) getSampleRate(), outl, outr);
pthread_mutex_unlock(&vmaster->mutex);
};
}
void VSTSynth::processReplacing (float **inputs, float **outputs, long sampleframes)
void VSTSynth::processReplacing(float **inputs,
float **outputs,
long sampleframes)
{
process(inputs,outputs,sampleframes);
};
process(inputs, outputs, sampleframes);
}
long int VSTSynth::canDo(char *txt)
{
if (strcmp(txt,"receiveVstEvents")==0) return (1);
if (strcmp(txt,"receiveVstMidiEvent")==0) return (1);
return(-1);
};
if(strcmp(txt, "receiveVstEvents") == 0)
return 1;
if(strcmp(txt, "receiveVstMidiEvent") == 0)
return 1;
return -1;
}
bool VSTSynth::getVendorString(char *txt)
{
strcpy(txt,"Nasca O. Paul");
return(true);
};
strcpy(txt, "Nasca O. Paul");
return true;
}
bool VSTSynth::getProductString(char *txt)
{
strcpy(txt,"ZynAddSubFX");
return(true);
};
strcpy(txt, "ZynAddSubFX");
return true;
}
void VSTSynth::resume()
{
wantEvents();
};
}

View File

@@ -32,26 +32,28 @@
class VSTSynth:public AudioEffectX
{
public:
VSTSynth (audioMasterCallback audioMaster);
~VSTSynth();
public:
VSTSynth(audioMasterCallback audioMaster);
~VSTSynth();
virtual void process (float **inputs, float **outputs, long sampleframes);
virtual void processReplacing (float **inputs, float **outputs, long sampleframes);
virtual long processEvents(VstEvents *events);//this is used for Midi input
virtual long int canDo(char *txt);
virtual bool getVendorString(char *txt);
virtual bool getProductString(char *txt);
virtual void resume();
virtual void process(float **inputs, float **outputs, long sampleframes);
virtual void processReplacing(float **inputs,
float **outputs,
long sampleframes);
virtual long processEvents(VstEvents *events); //this is used for Midi input
virtual long int canDo(char *txt);
virtual bool getVendorString(char *txt);
virtual bool getProductString(char *txt);
virtual void resume();
virtual long getChunk(void** data,bool isPreset=false);
virtual long setChunk(void *data,long size,bool isPreset=false);
virtual long getChunk(void **data, bool isPreset = false);
virtual long setChunk(void *data, long size, bool isPreset = false);
MasterUI *ui;
int Pexitprogram;
MasterUI *ui;
int Pexitprogram;
Master *vmaster;
pthread_t thr;
Master *vmaster;
pthread_t thr;
};
#endif

View File

@@ -23,77 +23,79 @@ using namespace std;
WAVaudiooutput::WAVaudiooutput()
{
file=NULL;
sampleswritten=0;
samplerate=44100;
};
file = NULL;
sampleswritten = 0;
samplerate = 44100;
}
WAVaudiooutput::~WAVaudiooutput()
{
close();
};
}
bool WAVaudiooutput::newfile(string filename,int samplerate,int channels)
bool WAVaudiooutput::newfile(string filename, int samplerate, int channels)
{
/**\todo Move this into the Constructor*/
close();//inchide un posibil fisier existent
file=fopen(filename.c_str(),"w");
if (!file) return false;
this->samplerate=samplerate;
this->channels=channels;
sampleswritten=0;
close(); //inchide un posibil fisier existent
file = fopen(filename.c_str(), "w");
if(!file)
return false;
this->samplerate = samplerate;
this->channels = channels;
sampleswritten = 0;
char tmp[44];
fwrite(tmp,1,44,file);
return(true);
};
fwrite(tmp, 1, 44, file);
return true;
}
void WAVaudiooutput::close()
{
if (file) {
if(file) {
unsigned int chunksize;
rewind(file);
fwrite("RIFF",4,1,file);
chunksize=sampleswritten*4+36;
fwrite(&chunksize,4,1,file);
fwrite("RIFF", 4, 1, file);
chunksize = sampleswritten * 4 + 36;
fwrite(&chunksize, 4, 1, file);
fwrite("WAVEfmt ",8,1,file);
chunksize=16;
fwrite(&chunksize,4,1,file);
unsigned short int formattag=1;//uncompresed wave
fwrite(&formattag,2,1,file);
unsigned short int nchannels=channels;//stereo
fwrite(&nchannels,2,1,file);
unsigned int samplerate_=samplerate;//samplerate
fwrite(&samplerate_,4,1,file);
unsigned int bytespersec=samplerate*2*channels;//bytes/sec
fwrite(&bytespersec,4,1,file);
unsigned short int blockalign=2*channels;//2 channels * 16 bits/8
fwrite(&blockalign,2,1,file);
unsigned short int bitspersample=16;
fwrite(&bitspersample,2,1,file);
fwrite("WAVEfmt ", 8, 1, file);
chunksize = 16;
fwrite(&chunksize, 4, 1, file);
unsigned short int formattag = 1; //uncompresed wave
fwrite(&formattag, 2, 1, file);
unsigned short int nchannels = channels; //stereo
fwrite(&nchannels, 2, 1, file);
unsigned int samplerate_ = samplerate; //samplerate
fwrite(&samplerate_, 4, 1, file);
unsigned int bytespersec = samplerate * 2 * channels; //bytes/sec
fwrite(&bytespersec, 4, 1, file);
unsigned short int blockalign = 2 * channels; //2 channels * 16 bits/8
fwrite(&blockalign, 2, 1, file);
unsigned short int bitspersample = 16;
fwrite(&bitspersample, 2, 1, file);
fwrite("data",4,1,file);
chunksize=sampleswritten*blockalign;
fwrite(&chunksize,4,1,file);
fwrite("data", 4, 1, file);
chunksize = sampleswritten * blockalign;
fwrite(&chunksize, 4, 1, file);
fclose(file);
file=NULL;
file = NULL;
}
};
}
void WAVaudiooutput::write_stereo_samples(int nsmps,short int *smps)
void WAVaudiooutput::write_stereo_samples(int nsmps, short int *smps)
{
if (!file) return;
fwrite(smps,nsmps,4,file);
sampleswritten+=nsmps;
};
if(!file)
return;
fwrite(smps, nsmps, 4, file);
sampleswritten += nsmps;
}
void WAVaudiooutput::write_mono_samples(int nsmps,short int *smps)
void WAVaudiooutput::write_mono_samples(int nsmps, short int *smps)
{
if (!file) return;
fwrite(smps,nsmps,2,file);
sampleswritten+=nsmps;
};
if(!file)
return;
fwrite(smps, nsmps, 2, file);
sampleswritten += nsmps;
}

View File

@@ -23,20 +23,21 @@
class WAVaudiooutput
{
public:
WAVaudiooutput();
~WAVaudiooutput();
public:
WAVaudiooutput();
~WAVaudiooutput();
bool newfile(std::string filename,int samplerate,int channels);
void close();
bool newfile(std::string filename, int samplerate, int channels);
void close();
void write_mono_samples(int nsmps, short int *smps);
void write_stereo_samples(int nsmps, short int *smps);
void write_mono_samples(int nsmps, short int *smps);
void write_stereo_samples(int nsmps, short int *smps);
private:
int sampleswritten;
int samplerate;
int channels;
FILE *file;
private:
int sampleswritten;
int samplerate;
int channels;
FILE *file;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -35,14 +35,16 @@
#include "../DSP/FFTwrapper.h"
#include "Presets.h"
enum FMTYPE {NONE,MORPH,RING_MOD,PHASE_MOD,FREQ_MOD,PITCH_MOD};
enum FMTYPE {
NONE, MORPH, RING_MOD, PHASE_MOD, FREQ_MOD, PITCH_MOD
};
extern int ADnote_unison_sizes[];
/*****************************************************************/
/* GLOBAL PARAMETERS */
/*****************************************************************/
struct ADnoteGlobalParam {
/* The instrument type - MONO/STEREO
If the mode is MONO, the panning of voices are not used
Stereo=1, Mono=0. */
@@ -53,35 +55,36 @@ struct ADnoteGlobalParam {
/******************************************
* FREQUENCY GLOBAL PARAMETERS *
******************************************/
unsigned short int PDetune;//fine detune
unsigned short int PCoarseDetune;//coarse detune+octave
unsigned char PDetuneType;//detune type
unsigned short int PDetune; //fine detune
unsigned short int PCoarseDetune; //coarse detune+octave
unsigned char PDetuneType; //detune type
unsigned char PBandwidth;//how much the relative fine detunes of the voices are changed
unsigned char PBandwidth; //how much the relative fine detunes of the voices are changed
EnvelopeParams *FreqEnvelope; //Frequency Envelope
EnvelopeParams *FreqEnvelope; //Frequency Envelope
LFOParams *FreqLfo;//Frequency LFO
LFOParams *FreqLfo; //Frequency LFO
/********************************************
* AMPLITUDE GLOBAL PARAMETERS *
********************************************/
/* Panning - 0 - random
1 - left
64 - center
127 - right */
unsigned char PPanning;
1 - left
64 - center
127 - right */
unsigned char PPanning;
unsigned char PVolume;
unsigned char PVolume;
unsigned char PAmpVelocityScaleFunction;
unsigned char PAmpVelocityScaleFunction;
EnvelopeParams *AmpEnvelope;
LFOParams *AmpLfo;
LFOParams *AmpLfo;
unsigned char PPunchStrength,PPunchTime,PPunchStretch,PPunchVelocitySensing;
unsigned char PPunchStrength, PPunchTime, PPunchStretch,
PPunchVelocitySensing;
/******************************************
* FILTER GLOBAL PARAMETERS *
@@ -92,11 +95,11 @@ struct ADnoteGlobalParam {
unsigned char PFilterVelocityScale;
// filter velocity sensing
unsigned char PFilterVelocityScaleFunction;
unsigned char PFilterVelocityScaleFunction;
EnvelopeParams *FilterEnvelope;
LFOParams *FilterLfo;
LFOParams *FilterLfo;
// RESONANCE
Resonance *Reson;
@@ -111,10 +114,27 @@ struct ADnoteGlobalParam {
/* VOICE PARAMETERS */
/***********************************************************/
struct ADnoteVoiceParam {
/** If the voice is enabled */
unsigned char Enabled;
/** How many subvoices are used in this voice */
unsigned char Unison_size;
/** How subvoices are spread */
unsigned char Unison_frequency_spread;
/** Stereo spread of the subvoices*/
unsigned char Unison_stereo_spread;
/** Vibratto of the subvoices (which makes the unison more "natural")*/
unsigned char Unison_vibratto;
/** Medium speed of the vibratto of the subvoices*/
unsigned char Unison_vibratto_speed;
/** Unison invert phase */
unsigned char Unison_invert_phase; //0=none,1=random,2=50%,3=33%,4=25%
/** Type of the voice (0=Sound,1=Noise)*/
unsigned char Type;
@@ -125,11 +145,11 @@ struct ADnoteVoiceParam {
unsigned char Presonance;
// What external oscil should I use, -1 for internal OscilSmp&FMSmp
short int Pextoscil,PextFMoscil;
short int Pextoscil, PextFMoscil;
// it is not allowed that the externoscil,externFMoscil => current voice
// oscillator phases
unsigned char Poscilphase,PFMoscilphase;
unsigned char Poscilphase, PFMoscilphase;
// filter bypass
unsigned char Pfilterbypass;
@@ -159,12 +179,12 @@ struct ADnoteVoiceParam {
unsigned char PDetuneType;
/* Frequency Envelope */
unsigned char PFreqEnvelopeEnabled;
unsigned char PFreqEnvelopeEnabled;
EnvelopeParams *FreqEnvelope;
/* Frequency LFO */
unsigned char PFreqLfoEnabled;
LFOParams *FreqLfo;
LFOParams *FreqLfo;
/***************************
@@ -172,9 +192,9 @@ struct ADnoteVoiceParam {
***************************/
/* Panning 0 - random
1 - left
64 - center
127 - right
1 - left
64 - center
127 - right
The Panning is ignored if the instrument is mono */
unsigned char PPanning;
@@ -188,12 +208,12 @@ struct ADnoteVoiceParam {
unsigned char PAmpVelocityScaleFunction;
/* Amplitude Envelope */
unsigned char PAmpEnvelopeEnabled;
unsigned char PAmpEnvelopeEnabled;
EnvelopeParams *AmpEnvelope;
/* Amplitude LFO */
unsigned char PAmpLfoEnabled;
LFOParams *AmpLfo;
LFOParams *AmpLfo;
@@ -206,12 +226,12 @@ struct ADnoteVoiceParam {
FilterParams *VoiceFilter;
/* Filter Envelope */
unsigned char PFilterEnvelopeEnabled;
unsigned char PFilterEnvelopeEnabled;
EnvelopeParams *FilterEnvelope;
/* LFO Envelope */
unsigned char PFilterLfoEnabled;
LFOParams *FilterLfo;
LFOParams *FilterLfo;
/****************************
* MODULLATOR PARAMETERS *
@@ -247,37 +267,41 @@ struct ADnoteVoiceParam {
unsigned char PFMDetuneType;
/* Frequency Envelope of the Modullator */
unsigned char PFMFreqEnvelopeEnabled;
unsigned char PFMFreqEnvelopeEnabled;
EnvelopeParams *FMFreqEnvelope;
/* Frequency Envelope of the Modullator */
unsigned char PFMAmpEnvelopeEnabled;
unsigned char PFMAmpEnvelopeEnabled;
EnvelopeParams *FMAmpEnvelope;
};
class ADnoteParameters:public Presets
{
public:
ADnoteParameters(FFTwrapper *fft_);
~ADnoteParameters();
public:
ADnoteParameters(FFTwrapper *fft_);
~ADnoteParameters();
ADnoteGlobalParam GlobalPar;
ADnoteVoiceParam VoicePar[NUM_VOICES];
ADnoteGlobalParam GlobalPar;
ADnoteVoiceParam VoicePar[NUM_VOICES];
void defaults();
void add2XML(XMLwrapper *xml);
void getfromXML(XMLwrapper *xml);
void defaults();
void add2XML(XMLwrapper *xml);
void getfromXML(XMLwrapper *xml);
REALTYPE getBandwidthDetuneMultiplier();
private:
void defaults(int n);//n is the nvoice
REALTYPE getBandwidthDetuneMultiplier();
REALTYPE getUnisonFrequencySpreadCents(int nvoice);
int get_unison_size_index(int nvoice);
void set_unison_size_index(int nvoice, int index);
private:
void defaults(int n); //n is the nvoice
void EnableVoice(int nvoice);
void KillVoice(int nvoice);
FFTwrapper *fft;
void EnableVoice(int nvoice);
void KillVoice(int nvoice);
FFTwrapper *fft;
void add2XMLsection(XMLwrapper *xml,int n);
void getfromXMLsection(XMLwrapper *xml,int n);
void add2XMLsection(XMLwrapper *xml, int n);
void getfromXMLsection(XMLwrapper *xml, int n);
};
#endif

View File

@@ -28,50 +28,48 @@ Controller::Controller()
{
defaults();
resetall();
};
}
Controller::~Controller()
{
};
{}
void Controller::defaults()
{
setpitchwheelbendrange(200);//2 halftones
expression.receive=1;
panning.depth=64;
filtercutoff.depth=64;
filterq.depth=64;
bandwidth.depth=64;
bandwidth.exponential=0;
modwheel.depth=80;
modwheel.exponential=0;
fmamp.receive=1;
volume.receive=1;
sustain.receive=1;
NRPN.receive=1;
setpitchwheelbendrange(200); //2 halftones
expression.receive = 1;
panning.depth = 64;
filtercutoff.depth = 64;
filterq.depth = 64;
bandwidth.depth = 64;
bandwidth.exponential = 0;
modwheel.depth = 80;
modwheel.exponential = 0;
fmamp.receive = 1;
volume.receive = 1;
sustain.receive = 1;
NRPN.receive = 1;
portamento.portamento=0;
portamento.used=0;
portamento.proportional=0;
portamento.propRate=80;
portamento.propDepth=90;
portamento.receive=1;
portamento.time=64;
portamento.updowntimestretch=64;
portamento.pitchthresh=3;
portamento.pitchthreshtype=1;
portamento.noteusing=-1;
resonancecenter.depth=64;
resonancebandwidth.depth=64;
portamento.portamento = 0;
portamento.used = 0;
portamento.proportional = 0;
portamento.propRate = 80;
portamento.propDepth = 90;
portamento.receive = 1;
portamento.time = 64;
portamento.updowntimestretch = 64;
portamento.pitchthresh = 3;
portamento.pitchthreshtype = 1;
portamento.noteusing = -1;
resonancecenter.depth = 64;
resonancebandwidth.depth = 64;
initportamento(440.0,440.0,false); // Now has a third argument
initportamento(440.0, 440.0, false); // Now has a third argument
setportamento(0);
};
}
void Controller::resetall()
{
setpitchwheel(0);//center
setpitchwheel(0); //center
setexpression(127);
setpanning(64);
setfiltercutoff(64);
@@ -85,276 +83,333 @@ void Controller::resetall()
setresonancebw(64);
//reset the NRPN
NRPN.parhi=-1;
NRPN.parlo=-1;
NRPN.valhi=-1;
NRPN.vallo=-1;
};
NRPN.parhi = -1;
NRPN.parlo = -1;
NRPN.valhi = -1;
NRPN.vallo = -1;
}
void Controller::setpitchwheel(int value)
{
pitchwheel.data=value;
REALTYPE cents=value/8192.0;
cents*=pitchwheel.bendrange;
pitchwheel.relfreq=pow(2,cents/1200.0);
pitchwheel.data = value;
REALTYPE cents = value / 8192.0;
cents *= pitchwheel.bendrange;
pitchwheel.relfreq = pow(2, cents / 1200.0);
//fprintf(stderr,"%ld %ld -> %.3f\n",pitchwheel.bendrange,pitchwheel.data,pitchwheel.relfreq);fflush(stderr);
};
}
void Controller::setpitchwheelbendrange(unsigned short int value)
{
pitchwheel.bendrange=value;
};
pitchwheel.bendrange = value;
}
void Controller::setexpression(int value)
{
expression.data=value;
if (expression.receive!=0) expression.relvolume=value/127.0;
else expression.relvolume=1.0;
};
expression.data = value;
if(expression.receive != 0)
expression.relvolume = value / 127.0;
else
expression.relvolume = 1.0;
}
void Controller::setpanning(int value)
{
panning.data=value;
panning.pan=(value/128.0-0.5)*(panning.depth/64.0);
};
panning.data = value;
panning.pan = (value / 128.0 - 0.5) * (panning.depth / 64.0);
}
void Controller::setfiltercutoff(int value)
{
filtercutoff.data=value;
filtercutoff.relfreq=(value-64.0)*filtercutoff.depth/4096.0*3.321928;//3.3219..=ln2(10)
};
filtercutoff.data = value;
filtercutoff.relfreq =
(value - 64.0) * filtercutoff.depth / 4096.0 * 3.321928; //3.3219..=ln2(10)
}
void Controller::setfilterq(int value)
{
filterq.data=value;
filterq.relq=pow(30.0,(value-64.0)/64.0*(filterq.depth/64.0));
};
filterq.data = value;
filterq.relq = pow(30.0, (value - 64.0) / 64.0 * (filterq.depth / 64.0));
}
void Controller::setbandwidth(int value)
{
bandwidth.data=value;
if (bandwidth.exponential==0) {
REALTYPE tmp=pow(25.0,pow(bandwidth.depth/127.0,1.5))-1.0;
if ((value<64)&&(bandwidth.depth>=64)) tmp=1.0;
bandwidth.relbw=(value/64.0-1.0)*tmp+1.0;
if (bandwidth.relbw<0.01) bandwidth.relbw=0.01;
} else {
bandwidth.relbw=pow(25.0,(value-64.0)/64.0*(bandwidth.depth/64.0));
};
};
bandwidth.data = value;
if(bandwidth.exponential == 0) {
REALTYPE tmp = pow(25.0, pow(bandwidth.depth / 127.0, 1.5)) - 1.0;
if((value < 64) && (bandwidth.depth >= 64))
tmp = 1.0;
bandwidth.relbw = (value / 64.0 - 1.0) * tmp + 1.0;
if(bandwidth.relbw < 0.01)
bandwidth.relbw = 0.01;
}
else
bandwidth.relbw =
pow(25.0, (value - 64.0) / 64.0 * (bandwidth.depth / 64.0));
;
}
void Controller::setmodwheel(int value)
{
modwheel.data=value;
if (modwheel.exponential==0) {
REALTYPE tmp=pow(25.0,pow(modwheel.depth/127.0,1.5)*2.0)/25.0;
if ((value<64)&&(modwheel.depth>=64)) tmp=1.0;
modwheel.relmod=(value/64.0-1.0)*tmp+1.0;
if (modwheel.relmod<0.0) modwheel.relmod=0.0;
} else modwheel.relmod=pow(25.0,(value-64.0)/64.0*(modwheel.depth/80.0));
};
modwheel.data = value;
if(modwheel.exponential == 0) {
REALTYPE tmp = pow(25.0, pow(modwheel.depth / 127.0, 1.5) * 2.0) / 25.0;
if((value < 64) && (modwheel.depth >= 64))
tmp = 1.0;
modwheel.relmod = (value / 64.0 - 1.0) * tmp + 1.0;
if(modwheel.relmod < 0.0)
modwheel.relmod = 0.0;
}
else
modwheel.relmod =
pow(25.0, (value - 64.0) / 64.0 * (modwheel.depth / 80.0));
}
void Controller::setfmamp(int value)
{
fmamp.data=value;
fmamp.relamp=value/127.0;
if (fmamp.receive!=0) fmamp.relamp=value/127.0;
else fmamp.relamp=1.0;
};
fmamp.data = value;
fmamp.relamp = value / 127.0;
if(fmamp.receive != 0)
fmamp.relamp = value / 127.0;
else
fmamp.relamp = 1.0;
}
void Controller::setvolume(int value)
{
volume.data=value;
if (volume.receive!=0) volume.volume=pow(0.1,(127-value)/127.0*2.0);
else volume.volume=1.0;
};
volume.data = value;
if(volume.receive != 0)
volume.volume = pow(0.1, (127 - value) / 127.0 * 2.0);
else
volume.volume = 1.0;
}
void Controller::setsustain(int value)
{
sustain.data=value;
if (sustain.receive!=0) sustain.sustain=((value<64) ? 0 : 1 );
else sustain.sustain=0;
};
sustain.data = value;
if(sustain.receive != 0)
sustain.sustain = ((value < 64) ? 0 : 1);
else
sustain.sustain = 0;
}
void Controller::setportamento(int value)
{
portamento.data=value;
if (portamento.receive!=0) portamento.portamento=((value<64) ? 0 : 1 );
};
portamento.data = value;
if(portamento.receive != 0)
portamento.portamento = ((value < 64) ? 0 : 1);
}
int Controller::initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag)
int Controller::initportamento(REALTYPE oldfreq,
REALTYPE newfreq,
bool legatoflag)
{
portamento.x=0.0;
portamento.x = 0.0;
if (legatoflag) { // Legato in progress
if (portamento.portamento==0) return(0);
} else { // No legato, do the original if...return
if ((portamento.used!=0) || (portamento.portamento==0)) return(0);
};
if(legatoflag) { // Legato in progress
if(portamento.portamento == 0)
return 0;
}
else // No legato, do the original if...return
if((portamento.used != 0) || (portamento.portamento == 0))
return 0;
;
REALTYPE portamentotime=pow(100.0,portamento.time/127.0)/50.0;//portamento time in seconds
if (portamento.proportional) {
REALTYPE portamentotime = pow(100.0, portamento.time / 127.0) / 50.0; //portamento time in seconds
if(portamento.proportional) {
//If there is a min(float,float) and a max(float,float) then they
//could be used here
//Linear functors could also make this nicer
if(oldfreq > newfreq) //2 is the center of propRate
portamentotime *= pow(oldfreq/newfreq/(portamento.propRate/127.0*3+.05),
(portamento.propDepth/127.0*1.6+.2));
portamentotime *=
pow(oldfreq / newfreq / (portamento.propRate / 127.0 * 3 + .05),
(portamento.propDepth / 127.0 * 1.6 + .2));
else //1 is the center of propDepth
portamentotime *= pow(newfreq/oldfreq/(portamento.propRate/127.0*3+.05),
(portamento.propDepth/127.0*1.6+.2));
portamentotime *=
pow(newfreq / oldfreq / (portamento.propRate / 127.0 * 3 + .05),
(portamento.propDepth / 127.0 * 1.6 + .2));
}
if ((portamento.updowntimestretch>=64)&&(newfreq<oldfreq)) {
if (portamento.updowntimestretch==127) return(0);
portamentotime*=pow(0.1,(portamento.updowntimestretch-64)/63.0);
if((portamento.updowntimestretch >= 64) && (newfreq < oldfreq)) {
if(portamento.updowntimestretch == 127)
return 0;
portamentotime *= pow(0.1, (portamento.updowntimestretch - 64) / 63.0);
}
if((portamento.updowntimestretch < 64) && (newfreq > oldfreq)) {
if(portamento.updowntimestretch == 0)
return 0;
portamentotime *= pow(0.1, (64.0 - portamento.updowntimestretch) / 64.0);
}
if ((portamento.updowntimestretch<64)&&(newfreq>oldfreq)) {
if (portamento.updowntimestretch==0) return(0);
portamentotime*=pow(0.1,(64.0-portamento.updowntimestretch)/64.0);
};
//printf("%f->%f : Time %f\n",oldfreq,newfreq,portamentotime);
portamento.dx=SOUND_BUFFER_SIZE/(portamentotime*SAMPLE_RATE);
portamento.origfreqrap=oldfreq/newfreq;
portamento.dx = SOUND_BUFFER_SIZE / (portamentotime * SAMPLE_RATE);
portamento.origfreqrap = oldfreq / newfreq;
REALTYPE tmprap=( (portamento.origfreqrap>1.0) ?
(portamento.origfreqrap) :
(1.0/portamento.origfreqrap) );
REALTYPE tmprap = ((portamento.origfreqrap > 1.0) ?
(portamento.origfreqrap) :
(1.0 / portamento.origfreqrap));
REALTYPE thresholdrap=pow(2.0,portamento.pitchthresh/12.0);
if ((portamento.pitchthreshtype==0) && (tmprap-0.00001>thresholdrap) ) return(0);
if ((portamento.pitchthreshtype==1) && (tmprap+0.00001<thresholdrap) ) return(0);
REALTYPE thresholdrap = pow(2.0, portamento.pitchthresh / 12.0);
if((portamento.pitchthreshtype == 0) && (tmprap - 0.00001 > thresholdrap))
return 0;
if((portamento.pitchthreshtype == 1) && (tmprap + 0.00001 < thresholdrap))
return 0;
portamento.used=1;
portamento.freqrap=portamento.origfreqrap;
return (1);
};
portamento.used = 1;
portamento.freqrap = portamento.origfreqrap;
return 1;
}
void Controller::updateportamento()
{
if (portamento.used==0) return;
if(portamento.used == 0)
return;
portamento.x+=portamento.dx;
if (portamento.x>1.0) {
portamento.x=1.0;
portamento.used=0;
};
portamento.freqrap=(1.0-portamento.x)*portamento.origfreqrap+portamento.x;
};
portamento.x += portamento.dx;
if(portamento.x > 1.0) {
portamento.x = 1.0;
portamento.used = 0;
}
portamento.freqrap =
(1.0 - portamento.x) * portamento.origfreqrap + portamento.x;
}
void Controller::setresonancecenter(int value)
{
resonancecenter.data=value;
resonancecenter.relcenter=pow(3.0,(value-64.0)/64.0*(resonancecenter.depth/64.0));
};
resonancecenter.data = value;
resonancecenter.relcenter =
pow(3.0, (value - 64.0) / 64.0 * (resonancecenter.depth / 64.0));
}
void Controller::setresonancebw(int value)
{
resonancebandwidth.data=value;
resonancebandwidth.relbw=pow(1.5,(value-64.0)/64.0*(resonancebandwidth.depth/127.0));
};
resonancebandwidth.data = value;
resonancebandwidth.relbw =
pow(1.5, (value - 64.0) / 64.0 * (resonancebandwidth.depth / 127.0));
}
//Returns 0 if there is NRPN or 1 if there is not
int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo)
{
if (NRPN.receive==0) return(1);
if ((NRPN.parhi<0)||(NRPN.parlo<0)||(NRPN.valhi<0)||(NRPN.vallo<0))
return(1);
if(NRPN.receive == 0)
return 1;
if((NRPN.parhi < 0) || (NRPN.parlo < 0) || (NRPN.valhi < 0)
|| (NRPN.vallo < 0))
return 1;
*parhi=NRPN.parhi;
*parlo=NRPN.parlo;
*valhi=NRPN.valhi;
*vallo=NRPN.vallo;
return(0);
};
*parhi = NRPN.parhi;
*parlo = NRPN.parlo;
*valhi = NRPN.valhi;
*vallo = NRPN.vallo;
return 0;
}
void Controller::setparameternumber(unsigned int type,int value)
void Controller::setparameternumber(unsigned int type, int value)
{
switch (type) {
switch(type) {
case C_nrpnhi:
NRPN.parhi=value;
NRPN.valhi=-1;
NRPN.vallo=-1;//clear the values
NRPN.parhi = value;
NRPN.valhi = -1;
NRPN.vallo = -1; //clear the values
break;
case C_nrpnlo:
NRPN.parlo=value;
NRPN.valhi=-1;
NRPN.vallo=-1;//clear the values
NRPN.parlo = value;
NRPN.valhi = -1;
NRPN.vallo = -1; //clear the values
break;
case C_dataentryhi:
if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.valhi=value;
if((NRPN.parhi >= 0) && (NRPN.parlo >= 0))
NRPN.valhi = value;
break;
case C_dataentrylo:
if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.vallo=value;
if((NRPN.parhi >= 0) && (NRPN.parlo >= 0))
NRPN.vallo = value;
break;
};
};
}
}
void Controller::add2XML(XMLwrapper *xml)
{
xml->addpar("pitchwheel_bendrange",pitchwheel.bendrange);
xml->addpar("pitchwheel_bendrange", pitchwheel.bendrange);
xml->addparbool("expression_receive",expression.receive);
xml->addpar("panning_depth",panning.depth);
xml->addpar("filter_cutoff_depth",filtercutoff.depth);
xml->addpar("filter_q_depth",filterq.depth);
xml->addpar("bandwidth_depth",bandwidth.depth);
xml->addpar("mod_wheel_depth",modwheel.depth);
xml->addparbool("mod_wheel_exponential",modwheel.exponential);
xml->addparbool("fm_amp_receive",fmamp.receive);
xml->addparbool("volume_receive",volume.receive);
xml->addparbool("sustain_receive",sustain.receive);
xml->addparbool("expression_receive", expression.receive);
xml->addpar("panning_depth", panning.depth);
xml->addpar("filter_cutoff_depth", filtercutoff.depth);
xml->addpar("filter_q_depth", filterq.depth);
xml->addpar("bandwidth_depth", bandwidth.depth);
xml->addpar("mod_wheel_depth", modwheel.depth);
xml->addparbool("mod_wheel_exponential", modwheel.exponential);
xml->addparbool("fm_amp_receive", fmamp.receive);
xml->addparbool("volume_receive", volume.receive);
xml->addparbool("sustain_receive", sustain.receive);
xml->addparbool("portamento_receive",portamento.receive);
xml->addpar("portamento_time",portamento.time);
xml->addpar("portamento_pitchthresh",portamento.pitchthresh);
xml->addpar("portamento_pitchthreshtype",portamento.pitchthreshtype);
xml->addpar("portamento_portamento",portamento.portamento);
xml->addpar("portamento_updowntimestretch",portamento.updowntimestretch);
xml->addpar("portamento_proportional",portamento.proportional);
xml->addpar("portamento_proprate",portamento.propRate);
xml->addpar("portamento_propdepth",portamento.propDepth);
xml->addparbool("portamento_receive", portamento.receive);
xml->addpar("portamento_time", portamento.time);
xml->addpar("portamento_pitchthresh", portamento.pitchthresh);
xml->addpar("portamento_pitchthreshtype", portamento.pitchthreshtype);
xml->addpar("portamento_portamento", portamento.portamento);
xml->addpar("portamento_updowntimestretch", portamento.updowntimestretch);
xml->addpar("portamento_proportional", portamento.proportional);
xml->addpar("portamento_proprate", portamento.propRate);
xml->addpar("portamento_propdepth", portamento.propDepth);
xml->addpar("resonance_center_depth",resonancecenter.depth);
xml->addpar("resonance_bandwidth_depth",resonancebandwidth.depth);
};
xml->addpar("resonance_center_depth", resonancecenter.depth);
xml->addpar("resonance_bandwidth_depth", resonancebandwidth.depth);
}
void Controller::getfromXML(XMLwrapper *xml)
{
pitchwheel.bendrange=xml->getpar("pitchwheel_bendrange",pitchwheel.bendrange,-6400,6400);
pitchwheel.bendrange = xml->getpar("pitchwheel_bendrange",
pitchwheel.bendrange,
-6400,
6400);
expression.receive=xml->getparbool("expression_receive",expression.receive);
panning.depth=xml->getpar127("panning_depth",panning.depth);
filtercutoff.depth=xml->getpar127("filter_cutoff_depth",filtercutoff.depth);
filterq.depth=xml->getpar127("filter_q_depth",filterq.depth);
bandwidth.depth=xml->getpar127("bandwidth_depth",bandwidth.depth);
modwheel.depth=xml->getpar127("mod_wheel_depth",modwheel.depth);
modwheel.exponential=xml->getparbool("mod_wheel_exponential",modwheel.exponential);
fmamp.receive=xml->getparbool("fm_amp_receive",fmamp.receive);
volume.receive=xml->getparbool("volume_receive",volume.receive);
sustain.receive=xml->getparbool("sustain_receive",sustain.receive);
expression.receive = xml->getparbool("expression_receive",
expression.receive);
panning.depth = xml->getpar127("panning_depth", panning.depth);
filtercutoff.depth = xml->getpar127("filter_cutoff_depth",
filtercutoff.depth);
filterq.depth = xml->getpar127("filter_q_depth", filterq.depth);
bandwidth.depth = xml->getpar127("bandwidth_depth", bandwidth.depth);
modwheel.depth = xml->getpar127("mod_wheel_depth", modwheel.depth);
modwheel.exponential = xml->getparbool("mod_wheel_exponential",
modwheel.exponential);
fmamp.receive = xml->getparbool("fm_amp_receive",
fmamp.receive);
volume.receive = xml->getparbool("volume_receive",
volume.receive);
sustain.receive = xml->getparbool("sustain_receive",
sustain.receive);
portamento.receive=xml->getparbool("portamento_receive",portamento.receive);
portamento.time=xml->getpar127("portamento_time",portamento.time);
portamento.pitchthresh=xml->getpar127("portamento_pitchthresh",portamento.pitchthresh);
portamento.pitchthreshtype=xml->getpar127("portamento_pitchthreshtype",portamento.pitchthreshtype);
portamento.portamento=xml->getpar127("portamento_portamento",portamento.portamento);
portamento.updowntimestretch=xml->getpar127("portamento_updowntimestretch",portamento.updowntimestretch);
portamento.proportional=xml->getpar127("portamento_proportional",portamento.proportional);
portamento.propRate=xml->getpar127("portamento_proprate",portamento.propRate);
portamento.propDepth=xml->getpar127("portamento_propdepth",portamento.propDepth);
resonancecenter.depth=xml->getpar127("resonance_center_depth",resonancecenter.depth);
resonancebandwidth.depth=xml->getpar127("resonance_bandwidth_depth",resonancebandwidth.depth);
};
portamento.receive = xml->getparbool("portamento_receive",
portamento.receive);
portamento.time = xml->getpar127("portamento_time",
portamento.time);
portamento.pitchthresh = xml->getpar127("portamento_pitchthresh",
portamento.pitchthresh);
portamento.pitchthreshtype = xml->getpar127("portamento_pitchthreshtype",
portamento.pitchthreshtype);
portamento.portamento = xml->getpar127("portamento_portamento",
portamento.portamento);
portamento.updowntimestretch = xml->getpar127(
"portamento_updowntimestretch",
portamento.updowntimestretch);
portamento.proportional = xml->getpar127("portamento_proportional",
portamento.proportional);
portamento.propRate = xml->getpar127("portamento_proprate",
portamento.propRate);
portamento.propDepth = xml->getpar127("portamento_propdepth",
portamento.propDepth);
resonancecenter.depth = xml->getpar127("resonance_center_depth",
resonancecenter.depth);
resonancebandwidth.depth = xml->getpar127("resonance_bandwidth_depth",
resonancebandwidth.depth);
}

View File

@@ -30,191 +30,191 @@
/**(Midi) Controllers implementation*/
class Controller
{
public:
Controller();
~Controller();
void resetall();
public:
Controller();
~Controller();
void resetall();
void add2XML(XMLwrapper *xml);
void defaults();
void getfromXML(XMLwrapper *xml);
void add2XML(XMLwrapper *xml);
void defaults();
void getfromXML(XMLwrapper *xml);
//Controllers functions
void setpitchwheel(int value);
void setpitchwheelbendrange(unsigned short int value);
void setexpression(int value);
void setpanning(int value);
void setfiltercutoff(int value);
void setfilterq(int value);
void setbandwidth(int value);
void setmodwheel(int value);
void setfmamp(int value);
void setvolume(int value);
void setsustain(int value);
/**Enable or disable portamento
* @param value 0-127 MIDI value (greater than 64 enables)*/
void setportamento(int value);
void setresonancecenter(int value);
void setresonancebw(int value);
//Controllers functions
void setpitchwheel(int value);
void setpitchwheelbendrange(unsigned short int value);
void setexpression(int value);
void setpanning(int value);
void setfiltercutoff(int value);
void setfilterq(int value);
void setbandwidth(int value);
void setmodwheel(int value);
void setfmamp(int value);
void setvolume(int value);
void setsustain(int value);
/**Enable or disable portamento
* @param value 0-127 MIDI value (greater than 64 enables)*/
void setportamento(int value);
void setresonancecenter(int value);
void setresonancebw(int value);
void setparameternumber(unsigned int type,int value);//used for RPN and NRPN's
int getnrpn(int *parhi, int *parlo, int *valhi, int *vallo);
void setparameternumber(unsigned int type, int value); //used for RPN and NRPN's
int getnrpn(int *parhi, int *parlo, int *valhi, int *vallo);
/**
* Initialize a portamento
*
* @param oldfreq Starting frequency of the portamento (Hz)
* @param newfreq Ending frequency of the portamento (Hz)
* @param legatoflag true when legato is in progress, false otherwise
* @returns 1 if properly initialized, 0 otherwise*/
int initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag);
/**Update portamento's freqrap to next value based upon dx*/
void updateportamento();
// Controllers values
struct {//Pitch Wheel
int data;
short int bendrange;//bendrange is in cents
REALTYPE relfreq;//the relative frequency (default is 1.0)
} pitchwheel;
struct {//Expression
int data;
REALTYPE relvolume;
unsigned char receive;
} expression;
struct {//Panning
int data;
REALTYPE pan;
unsigned char depth;
} panning;
struct {//Filter cutoff
int data;
REALTYPE relfreq;
unsigned char depth;
} filtercutoff;
struct {//Filter Q
int data;
REALTYPE relq;
unsigned char depth;
} filterq;
struct {//Bandwidth
int data;
REALTYPE relbw;
unsigned char depth;
unsigned char exponential;
} bandwidth;
struct {//Modulation Wheel
int data;
REALTYPE relmod;
unsigned char depth;
unsigned char exponential;
} modwheel;
struct {//FM amplitude
int data;
REALTYPE relamp;
unsigned char receive;
} fmamp;
struct {//Volume
int data;
REALTYPE volume;
unsigned char receive;
} volume;
struct {//Sustain
int data,sustain;
unsigned char receive;
} sustain;
struct {/**<Portamento*/
//parameters
int data;
unsigned char portamento;
/**Whether the portamento midi events are received or not*/
unsigned char receive;
/** The time that it takes for the portamento to complete
/**
* Initialize a portamento
*
* Translates in an expontal fashion to 0 Seconds to 1.93 Seconds
* of completion time*/
unsigned char time;
/**If the portamento is proportinal to the distance spanned
*
* 0 - constant time(default)
* 1 - proportional*/
unsigned char proportional;
/**Rate of proportinal portamento*/
unsigned char propRate;
/**Depth of proportinal portamento*/
unsigned char propDepth;
/**pitchthresh is the threshold of enabling protamento*/
unsigned char pitchthresh;
/**enable the portamento only below(0)/above(1) the threshold*/
unsigned char pitchthreshtype;
* @param oldfreq Starting frequency of the portamento (Hz)
* @param newfreq Ending frequency of the portamento (Hz)
* @param legatoflag true when legato is in progress, false otherwise
* @returns 1 if properly initialized, 0 otherwise*/
int initportamento(REALTYPE oldfreq, REALTYPE newfreq, bool legatoflag);
/**Update portamento's freqrap to next value based upon dx*/
void updateportamento();
/**this value represent how the portamento time is reduced
* 0 - for down portamento
* 1-63 - the up portamento's time is smaller than the down portamento
* 64 - the portamento time is always the same
* 64-126 - the down portamento's time is smaller than the up portamento
* 127 - for upper portamento
* 'up portamento' means when the frequency is rising
* (eg: the portamento is from 200Hz to 300 Hz)
* 'down portamento' means when the frequency is lowering
* (eg: the portamento is from 300Hz to 200 Hz)
*/
unsigned char updowntimestretch;
/**this value is used to compute the actual portamento
*
* This is a multiplyer to change the frequency of the newer
* frequency to fit the profile of the portamento.
* This will be linear with respect to x.*/
REALTYPE freqrap;
/**this is used by the Part for knowing which note uses the portamento*/
int noteusing;
/**if a the portamento is used by a note
* \todo see if this can be a bool*/
int used;
// Controllers values
struct { //Pitch Wheel
int data;
short int bendrange; //bendrange is in cents
REALTYPE relfreq; //the relative frequency (default is 1.0)
} pitchwheel;
//Internal data
struct { //Expression
int data;
REALTYPE relvolume;
unsigned char receive;
} expression;
/**x is from 0.0 (start portamento) to 1.0 (finished portamento)*/
REALTYPE x;
/**dx is the increment to x when updateportamento is called*/
REALTYPE dx;
/** this is used for computing oldfreq value from x*/
REALTYPE origfreqrap;
} portamento;
struct {//Resonance Center Frequency
int data;
REALTYPE relcenter;
unsigned char depth;
} resonancecenter;
struct {//Resonance Bandwidth
int data;
REALTYPE relbw;
unsigned char depth;
} resonancebandwidth;
struct { //Panning
int data;
REALTYPE pan;
unsigned char depth;
} panning;
/** RPN and NPRPN */
struct {//nrpn
int parhi,parlo;
int valhi,vallo;
unsigned char receive;//this is saved to disk by Master
} NRPN;
struct { //Filter cutoff
int data;
REALTYPE relfreq;
unsigned char depth;
} filtercutoff;
private:
struct { //Filter Q
int data;
REALTYPE relq;
unsigned char depth;
} filterq;
struct { //Bandwidth
int data;
REALTYPE relbw;
unsigned char depth;
unsigned char exponential;
} bandwidth;
struct { //Modulation Wheel
int data;
REALTYPE relmod;
unsigned char depth;
unsigned char exponential;
} modwheel;
struct { //FM amplitude
int data;
REALTYPE relamp;
unsigned char receive;
} fmamp;
struct { //Volume
int data;
REALTYPE volume;
unsigned char receive;
} volume;
struct { //Sustain
int data, sustain;
unsigned char receive;
} sustain;
struct { /**<Portamento*/
//parameters
int data;
unsigned char portamento;
/**Whether the portamento midi events are received or not*/
unsigned char receive;
/** The time that it takes for the portamento to complete
*
* Translates in an expontal fashion to 0 Seconds to 1.93 Seconds
* of completion time*/
unsigned char time;
/**If the portamento is proportinal to the distance spanned
*
* 0 - constant time(default)
* 1 - proportional*/
unsigned char proportional;
/**Rate of proportinal portamento*/
unsigned char propRate;
/**Depth of proportinal portamento*/
unsigned char propDepth;
/**pitchthresh is the threshold of enabling protamento*/
unsigned char pitchthresh;
/**enable the portamento only below(0)/above(1) the threshold*/
unsigned char pitchthreshtype;
/**this value represent how the portamento time is reduced
* 0 - for down portamento
* 1-63 - the up portamento's time is smaller than the down portamento
* 64 - the portamento time is always the same
* 64-126 - the down portamento's time is smaller than the up portamento
* 127 - for upper portamento
* 'up portamento' means when the frequency is rising
* (eg: the portamento is from 200Hz to 300 Hz)
* 'down portamento' means when the frequency is lowering
* (eg: the portamento is from 300Hz to 200 Hz)
*/
unsigned char updowntimestretch;
/**this value is used to compute the actual portamento
*
* This is a multiplyer to change the frequency of the newer
* frequency to fit the profile of the portamento.
* This will be linear with respect to x.*/
REALTYPE freqrap;
/**this is used by the Part for knowing which note uses the portamento*/
int noteusing;
/**if a the portamento is used by a note
* \todo see if this can be a bool*/
int used;
//Internal data
/**x is from 0.0 (start portamento) to 1.0 (finished portamento)*/
REALTYPE x;
/**dx is the increment to x when updateportamento is called*/
REALTYPE dx;
/** this is used for computing oldfreq value from x*/
REALTYPE origfreqrap;
} portamento;
struct { //Resonance Center Frequency
int data;
REALTYPE relcenter;
unsigned char depth;
} resonancecenter;
struct { //Resonance Bandwidth
int data;
REALTYPE relbw;
unsigned char depth;
} resonancebandwidth;
/** RPN and NPRPN */
struct { //nrpn
int parhi, parlo;
int valhi, vallo;
unsigned char receive; //this is saved to disk by Master
} NRPN;
private:
};
#endif

View File

@@ -26,264 +26,273 @@
#include <stdlib.h>
#include "EnvelopeParams.h"
EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_):Presets()
EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_,
unsigned char Pforcedrelease_):Presets()
{
int i;
PA_dt=10;
PD_dt=10;
PR_dt=10;
PA_val=64;
PD_val=64;
PS_val=64;
PR_val=64;
PA_dt = 10;
PD_dt = 10;
PR_dt = 10;
PA_val = 64;
PD_val = 64;
PS_val = 64;
PR_val = 64;
for (i=0;i<MAX_ENVELOPE_POINTS;i++) {
Penvdt[i]=32;
Penvval[i]=64;
};
Penvdt[0]=0;//no used
Penvsustain=1;
Penvpoints=1;
Envmode=1;
Penvstretch=Penvstretch_;
Pforcedrelease=Pforcedrelease_;
Pfreemode=1;
Plinearenvelope=0;
for(i = 0; i < MAX_ENVELOPE_POINTS; i++) {
Penvdt[i] = 32;
Penvval[i] = 64;
}
Penvdt[0] = 0; //no used
Penvsustain = 1;
Penvpoints = 1;
Envmode = 1;
Penvstretch = Penvstretch_;
Pforcedrelease = Pforcedrelease_;
Pfreemode = 1;
Plinearenvelope = 0;
store2defaults();
};
}
EnvelopeParams::~EnvelopeParams()
{
};
{}
REALTYPE EnvelopeParams::getdt(char i)
{
REALTYPE result=(pow(2.0,Penvdt[(int)i]/127.0*12.0)-1.0)*10.0;//miliseconds
return(result);
};
REALTYPE result = (pow(2.0, Penvdt[(int)i] / 127.0 * 12.0) - 1.0) * 10.0; //miliseconds
return result;
}
/*
* ADSR/ASR... initialisations
*/
void EnvelopeParams::ADSRinit(char A_dt,char D_dt,char S_val,char R_dt)
void EnvelopeParams::ADSRinit(char A_dt, char D_dt, char S_val, char R_dt)
{
setpresettype("Penvamplitude");
Envmode=1;
PA_dt=A_dt;
PD_dt=D_dt;
PS_val=S_val;
PR_dt=R_dt;
Pfreemode=0;
Envmode = 1;
PA_dt = A_dt;
PD_dt = D_dt;
PS_val = S_val;
PR_dt = R_dt;
Pfreemode = 0;
converttofree();
store2defaults();
};
}
void EnvelopeParams::ADSRinit_dB(char A_dt,char D_dt,char S_val,char R_dt)
void EnvelopeParams::ADSRinit_dB(char A_dt, char D_dt, char S_val, char R_dt)
{
setpresettype("Penvamplitude");
Envmode=2;
PA_dt=A_dt;
PD_dt=D_dt;
PS_val=S_val;
PR_dt=R_dt;
Pfreemode=0;
Envmode = 2;
PA_dt = A_dt;
PD_dt = D_dt;
PS_val = S_val;
PR_dt = R_dt;
Pfreemode = 0;
converttofree();
store2defaults();
};
}
void EnvelopeParams::ASRinit(char A_val,char A_dt,char R_val,char R_dt)
void EnvelopeParams::ASRinit(char A_val, char A_dt, char R_val, char R_dt)
{
setpresettype("Penvfrequency");
Envmode=3;
PA_val=A_val;
PA_dt=A_dt;
PR_val=R_val;
PR_dt=R_dt;
Pfreemode=0;
Envmode = 3;
PA_val = A_val;
PA_dt = A_dt;
PR_val = R_val;
PR_dt = R_dt;
Pfreemode = 0;
converttofree();
store2defaults();
};
}
void EnvelopeParams::ADSRinit_filter(char A_val,char A_dt,char D_val,char D_dt,char R_dt,char R_val)
void EnvelopeParams::ADSRinit_filter(char A_val,
char A_dt,
char D_val,
char D_dt,
char R_dt,
char R_val)
{
setpresettype("Penvfilter");
Envmode=4;
PA_val=A_val;
PA_dt=A_dt;
PD_val=D_val;
PD_dt=D_dt;
PR_dt=R_dt;
PR_val=R_val;
Pfreemode=0;
Envmode = 4;
PA_val = A_val;
PA_dt = A_dt;
PD_val = D_val;
PD_dt = D_dt;
PR_dt = R_dt;
PR_val = R_val;
Pfreemode = 0;
converttofree();
store2defaults();
};
}
void EnvelopeParams::ASRinit_bw(char A_val,char A_dt,char R_val,char R_dt)
void EnvelopeParams::ASRinit_bw(char A_val, char A_dt, char R_val, char R_dt)
{
setpresettype("Penvbandwidth");
Envmode=5;
PA_val=A_val;
PA_dt=A_dt;
PR_val=R_val;
PR_dt=R_dt;
Pfreemode=0;
Envmode = 5;
PA_val = A_val;
PA_dt = A_dt;
PR_val = R_val;
PR_dt = R_dt;
Pfreemode = 0;
converttofree();
store2defaults();
};
}
/*
* Convert the Envelope to freemode
*/
void EnvelopeParams::converttofree()
{
switch (Envmode) {
switch(Envmode) {
case 1:
Penvpoints=4;
Penvsustain=2;
Penvval[0]=0;
Penvdt[1]=PA_dt;
Penvval[1]=127;
Penvdt[2]=PD_dt;
Penvval[2]=PS_val;
Penvdt[3]=PR_dt;
Penvval[3]=0;
Penvpoints = 4;
Penvsustain = 2;
Penvval[0] = 0;
Penvdt[1] = PA_dt;
Penvval[1] = 127;
Penvdt[2] = PD_dt;
Penvval[2] = PS_val;
Penvdt[3] = PR_dt;
Penvval[3] = 0;
break;
case 2:
Penvpoints=4;
Penvsustain=2;
Penvval[0]=0;
Penvdt[1]=PA_dt;
Penvval[1]=127;
Penvdt[2]=PD_dt;
Penvval[2]=PS_val;
Penvdt[3]=PR_dt;
Penvval[3]=0;
Penvpoints = 4;
Penvsustain = 2;
Penvval[0] = 0;
Penvdt[1] = PA_dt;
Penvval[1] = 127;
Penvdt[2] = PD_dt;
Penvval[2] = PS_val;
Penvdt[3] = PR_dt;
Penvval[3] = 0;
break;
case 3:
Penvpoints=3;
Penvsustain=1;
Penvval[0]=PA_val;
Penvdt[1]=PA_dt;
Penvval[1]=64;
Penvdt[2]=PR_dt;
Penvval[2]=PR_val;
Penvpoints = 3;
Penvsustain = 1;
Penvval[0] = PA_val;
Penvdt[1] = PA_dt;
Penvval[1] = 64;
Penvdt[2] = PR_dt;
Penvval[2] = PR_val;
break;
case 4:
Penvpoints=4;
Penvsustain=2;
Penvval[0]=PA_val;
Penvdt[1]=PA_dt;
Penvval[1]=PD_val;
Penvdt[2]=PD_dt;
Penvval[2]=64;
Penvdt[3]=PR_dt;
Penvval[3]=PR_val;
Penvpoints = 4;
Penvsustain = 2;
Penvval[0] = PA_val;
Penvdt[1] = PA_dt;
Penvval[1] = PD_val;
Penvdt[2] = PD_dt;
Penvval[2] = 64;
Penvdt[3] = PR_dt;
Penvval[3] = PR_val;
break;
case 5:
Penvpoints=3;
Penvsustain=1;
Penvval[0]=PA_val;
Penvdt[1]=PA_dt;
Penvval[1]=64;
Penvdt[2]=PR_dt;
Penvval[2]=PR_val;
Penvpoints = 3;
Penvsustain = 1;
Penvval[0] = PA_val;
Penvdt[1] = PA_dt;
Penvval[1] = 64;
Penvdt[2] = PR_dt;
Penvval[2] = PR_val;
break;
};
};
}
}
void EnvelopeParams::add2XML(XMLwrapper *xml)
{
xml->addparbool("free_mode",Pfreemode);
xml->addpar("env_points",Penvpoints);
xml->addpar("env_sustain",Penvsustain);
xml->addpar("env_stretch",Penvstretch);
xml->addparbool("forced_release",Pforcedrelease);
xml->addparbool("linear_envelope",Plinearenvelope);
xml->addpar("A_dt",PA_dt);
xml->addpar("D_dt",PD_dt);
xml->addpar("R_dt",PR_dt);
xml->addpar("A_val",PA_val);
xml->addpar("D_val",PD_val);
xml->addpar("S_val",PS_val);
xml->addpar("R_val",PR_val);
xml->addparbool("free_mode", Pfreemode);
xml->addpar("env_points", Penvpoints);
xml->addpar("env_sustain", Penvsustain);
xml->addpar("env_stretch", Penvstretch);
xml->addparbool("forced_release", Pforcedrelease);
xml->addparbool("linear_envelope", Plinearenvelope);
xml->addpar("A_dt", PA_dt);
xml->addpar("D_dt", PD_dt);
xml->addpar("R_dt", PR_dt);
xml->addpar("A_val", PA_val);
xml->addpar("D_val", PD_val);
xml->addpar("S_val", PS_val);
xml->addpar("R_val", PR_val);
if ((Pfreemode!=0)||(!xml->minimal)) {
for (int i=0;i<Penvpoints;i++) {
xml->beginbranch("POINT",i);
if (i!=0) xml->addpar("dt",Penvdt[i]);
xml->addpar("val",Penvval[i]);
if((Pfreemode != 0) || (!xml->minimal)) {
for(int i = 0; i < Penvpoints; i++) {
xml->beginbranch("POINT", i);
if(i != 0)
xml->addpar("dt", Penvdt[i]);
xml->addpar("val", Penvval[i]);
xml->endbranch();
};
};
};
}
}
}
void EnvelopeParams::getfromXML(XMLwrapper *xml)
{
Pfreemode=xml->getparbool("free_mode",Pfreemode);
Penvpoints=xml->getpar127("env_points",Penvpoints);
Penvsustain=xml->getpar127("env_sustain",Penvsustain);
Penvstretch=xml->getpar127("env_stretch",Penvstretch);
Pforcedrelease=xml->getparbool("forced_release",Pforcedrelease);
Plinearenvelope=xml->getparbool("linear_envelope",Plinearenvelope);
Pfreemode = xml->getparbool("free_mode", Pfreemode);
Penvpoints = xml->getpar127("env_points", Penvpoints);
Penvsustain = xml->getpar127("env_sustain", Penvsustain);
Penvstretch = xml->getpar127("env_stretch", Penvstretch);
Pforcedrelease = xml->getparbool("forced_release", Pforcedrelease);
Plinearenvelope = xml->getparbool("linear_envelope", Plinearenvelope);
PA_dt=xml->getpar127("A_dt",PA_dt);
PD_dt=xml->getpar127("D_dt",PD_dt);
PR_dt=xml->getpar127("R_dt",PR_dt);
PA_val=xml->getpar127("A_val",PA_val);
PD_val=xml->getpar127("D_val",PD_val);
PS_val=xml->getpar127("S_val",PS_val);
PR_val=xml->getpar127("R_val",PR_val);
PA_dt = xml->getpar127("A_dt", PA_dt);
PD_dt = xml->getpar127("D_dt", PD_dt);
PR_dt = xml->getpar127("R_dt", PR_dt);
PA_val = xml->getpar127("A_val", PA_val);
PD_val = xml->getpar127("D_val", PD_val);
PS_val = xml->getpar127("S_val", PS_val);
PR_val = xml->getpar127("R_val", PR_val);
for (int i=0;i<Penvpoints;i++) {
if (xml->enterbranch("POINT",i)==0) continue;
if (i!=0) Penvdt[i]=xml->getpar127("dt",Penvdt[i]);
Penvval[i]=xml->getpar127("val",Penvval[i]);
for(int i = 0; i < Penvpoints; i++) {
if(xml->enterbranch("POINT", i) == 0)
continue;
if(i != 0)
Penvdt[i] = xml->getpar127("dt", Penvdt[i]);
Penvval[i] = xml->getpar127("val", Penvval[i]);
xml->exitbranch();
};
}
if (!Pfreemode) converttofree();
};
if(!Pfreemode)
converttofree();
}
void EnvelopeParams::defaults()
{
Penvstretch=Denvstretch;
Pforcedrelease=Dforcedrelease;
Plinearenvelope=Dlinearenvelope;
PA_dt=DA_dt;
PD_dt=DD_dt;
PR_dt=DR_dt;
PA_val=DA_val;
PD_val=DD_val;
PS_val=DS_val;
PR_val=DR_val;
Pfreemode=0;
Penvstretch = Denvstretch;
Pforcedrelease = Dforcedrelease;
Plinearenvelope = Dlinearenvelope;
PA_dt = DA_dt;
PD_dt = DD_dt;
PR_dt = DR_dt;
PA_val = DA_val;
PD_val = DD_val;
PS_val = DS_val;
PR_val = DR_val;
Pfreemode = 0;
converttofree();
};
}
void EnvelopeParams::store2defaults()
{
Denvstretch=Penvstretch;
Dforcedrelease=Pforcedrelease;
Dlinearenvelope=Plinearenvelope;
DA_dt=PA_dt;
DD_dt=PD_dt;
DR_dt=PR_dt;
DA_val=PA_val;
DD_val=PD_val;
DS_val=PS_val;
DR_val=PR_val;
};
Denvstretch = Penvstretch;
Dforcedrelease = Pforcedrelease;
Dlinearenvelope = Plinearenvelope;
DA_dt = PA_dt;
DD_dt = PD_dt;
DR_dt = PR_dt;
DA_val = PA_val;
DD_val = PD_val;
DS_val = PS_val;
DR_val = PR_val;
}

View File

@@ -32,54 +32,58 @@
class EnvelopeParams:public Presets
{
public:
EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_);
~EnvelopeParams();
void ADSRinit(char A_dt,char D_dt,char S_val,char R_dt);
void ADSRinit_dB(char A_dt,char D_dt,char S_val,char R_dt);
void ASRinit(char A_val,char A_dt,char R_val,char R_dt);
void ADSRinit_filter(char A_val,char A_dt,char D_val,char D_dt,char R_dt,char R_val);
void ASRinit_bw(char A_val,char A_dt,char R_val,char R_dt);
void converttofree();
public:
EnvelopeParams(unsigned char Penvstretch_,
unsigned char Pforcedrelease_);
~EnvelopeParams();
void ADSRinit(char A_dt, char D_dt, char S_val, char R_dt);
void ADSRinit_dB(char A_dt, char D_dt, char S_val, char R_dt);
void ASRinit(char A_val, char A_dt, char R_val, char R_dt);
void ADSRinit_filter(char A_val,
char A_dt,
char D_val,
char D_dt,
char R_dt,
char R_val);
void ASRinit_bw(char A_val, char A_dt, char R_val, char R_dt);
void converttofree();
void add2XML(XMLwrapper *xml);
void defaults();
void getfromXML(XMLwrapper *xml);
void add2XML(XMLwrapper *xml);
void defaults();
void getfromXML(XMLwrapper *xml);
REALTYPE getdt(char i);
REALTYPE getdt(char i);
/* MIDI Parameters */
unsigned char Pfreemode;//1 daca este in modul free sau 0 daca este in mod ADSR,ASR,...
unsigned char Penvpoints;
unsigned char Penvsustain;//127 pentru dezactivat
unsigned char Penvdt[MAX_ENVELOPE_POINTS];
unsigned char Penvval[MAX_ENVELOPE_POINTS];
unsigned char Penvstretch;//64=normal stretch (piano-like), 0=no stretch
unsigned char Pforcedrelease;//0 - OFF, 1 - ON
unsigned char Plinearenvelope;//if the amplitude envelope is linear
/* MIDI Parameters */
unsigned char Pfreemode; //1 daca este in modul free sau 0 daca este in mod ADSR,ASR,...
unsigned char Penvpoints;
unsigned char Penvsustain; //127 pentru dezactivat
unsigned char Penvdt[MAX_ENVELOPE_POINTS];
unsigned char Penvval[MAX_ENVELOPE_POINTS];
unsigned char Penvstretch; //64=normal stretch (piano-like), 0=no stretch
unsigned char Pforcedrelease; //0 - OFF, 1 - ON
unsigned char Plinearenvelope; //if the amplitude envelope is linear
unsigned char PA_dt,PD_dt,PR_dt,
PA_val,PD_val,PS_val,PR_val;
unsigned char PA_dt, PD_dt, PR_dt,
PA_val, PD_val, PS_val, PR_val;
int Envmode;// 1 for ADSR parameters (linear amplitude)
// 2 for ADSR_dB parameters (dB amplitude)
// 3 for ASR parameters (frequency LFO)
// 4 for ADSR_filter parameters (filter parameters)
// 5 for ASR_bw parameters (bandwidth parameters)
private:
void store2defaults();
/* Default parameters */
unsigned char Denvstretch;
unsigned char Dforcedrelease;
unsigned char Dlinearenvelope;
unsigned char DA_dt,DD_dt,DR_dt,
DA_val,DD_val,DS_val,DR_val;
int Envmode; // 1 for ADSR parameters (linear amplitude)
// 2 for ADSR_dB parameters (dB amplitude)
// 3 for ASR parameters (frequency LFO)
// 4 for ADSR_filter parameters (filter parameters)
// 5 for ASR_bw parameters (bandwidth parameters)
private:
void store2defaults();
/* Default parameters */
unsigned char Denvstretch;
unsigned char Dforcedrelease;
unsigned char Dlinearenvelope;
unsigned char DA_dt, DD_dt, DR_dt,
DA_val, DD_val, DS_val, DR_val;
};
#endif

View File

@@ -25,58 +25,60 @@
#include <stdlib.h>
#include "FilterParams.h"
FilterParams::FilterParams(unsigned char Ptype_,unsigned char Pfreq_,unsigned char Pq_):Presets()
FilterParams::FilterParams(unsigned char Ptype_,
unsigned char Pfreq_,
unsigned char Pq_):Presets()
{
setpresettype("Pfilter");
Dtype=Ptype_;
Dfreq=Pfreq_;
Dq=Pq_;
Dtype = Ptype_;
Dfreq = Pfreq_;
Dq = Pq_;
changed=false;
changed = false;
defaults();
};
}
FilterParams::~FilterParams()
{
};
{}
void FilterParams::defaults()
{
Ptype=Dtype;
Pfreq=Dfreq;
Pq=Dq;
Ptype = Dtype;
Pfreq = Dfreq;
Pq = Dq;
Pstages=0;
Pfreqtrack=64;
Pgain=64;
Pcategory=0;
Pstages = 0;
Pfreqtrack = 64;
Pgain = 64;
Pcategory = 0;
Pnumformants=3;
Pformantslowness=64;
for (int j=0;j<FF_MAX_VOWELS;j++) {
Pnumformants = 3;
Pformantslowness = 64;
for(int j = 0; j < FF_MAX_VOWELS; j++)
defaults(j);
};
;
Psequencesize=3;
for (int i=0;i<FF_MAX_SEQUENCE;i++) Psequence[i].nvowel=i%FF_MAX_VOWELS;
Psequencesize = 3;
for(int i = 0; i < FF_MAX_SEQUENCE; i++)
Psequence[i].nvowel = i % FF_MAX_VOWELS;
Psequencestretch=40;
Psequencereversed=0;
Pcenterfreq=64;//1 kHz
Poctavesfreq=64;
Pvowelclearness=64;
};
Psequencestretch = 40;
Psequencereversed = 0;
Pcenterfreq = 64; //1 kHz
Poctavesfreq = 64;
Pvowelclearness = 64;
}
void FilterParams::defaults(int n)
{
int j=n;
for (int i=0;i<FF_MAX_FORMANTS;i++) {
Pvowels[j].formants[i].freq=(int)(RND*127.0);//some random freqs
Pvowels[j].formants[i].q=64;
Pvowels[j].formants[i].amp=127;
};
};
int j = n;
for(int i = 0; i < FF_MAX_FORMANTS; i++) {
Pvowels[j].formants[i].freq = (int)(RND * 127.0); //some random freqs
Pvowels[j].formants[i].q = 64;
Pvowels[j].formants[i].amp = 127;
}
}
/*
@@ -87,36 +89,38 @@ void FilterParams::getfromFilterParams(FilterParams *pars)
{
defaults();
if (pars==NULL) return;
if(pars == NULL)
return;
Ptype=pars->Ptype;
Pfreq=pars->Pfreq;
Pq=pars->Pq;
Ptype = pars->Ptype;
Pfreq = pars->Pfreq;
Pq = pars->Pq;
Pstages=pars->Pstages;
Pfreqtrack=pars->Pfreqtrack;
Pgain=pars->Pgain;
Pcategory=pars->Pcategory;
Pstages = pars->Pstages;
Pfreqtrack = pars->Pfreqtrack;
Pgain = pars->Pgain;
Pcategory = pars->Pcategory;
Pnumformants=pars->Pnumformants;
Pformantslowness=pars->Pformantslowness;
for (int j=0;j<FF_MAX_VOWELS;j++) {
for (int i=0;i<FF_MAX_FORMANTS;i++) {
Pvowels[j].formants[i].freq=pars->Pvowels[j].formants[i].freq;
Pvowels[j].formants[i].q=pars->Pvowels[j].formants[i].q;
Pvowels[j].formants[i].amp=pars->Pvowels[j].formants[i].amp;
};
};
Pnumformants = pars->Pnumformants;
Pformantslowness = pars->Pformantslowness;
for(int j = 0; j < FF_MAX_VOWELS; j++) {
for(int i = 0; i < FF_MAX_FORMANTS; i++) {
Pvowels[j].formants[i].freq = pars->Pvowels[j].formants[i].freq;
Pvowels[j].formants[i].q = pars->Pvowels[j].formants[i].q;
Pvowels[j].formants[i].amp = pars->Pvowels[j].formants[i].amp;
}
}
Psequencesize=pars->Psequencesize;
for (int i=0;i<FF_MAX_SEQUENCE;i++) Psequence[i].nvowel=pars->Psequence[i].nvowel;
Psequencesize = pars->Psequencesize;
for(int i = 0; i < FF_MAX_SEQUENCE; i++)
Psequence[i].nvowel = pars->Psequence[i].nvowel;
Psequencestretch=pars->Psequencestretch;
Psequencereversed=pars->Psequencereversed;
Pcenterfreq=pars->Pcenterfreq;
Poctavesfreq=pars->Poctavesfreq;
Pvowelclearness=pars->Pvowelclearness;
};
Psequencestretch = pars->Psequencestretch;
Psequencereversed = pars->Psequencereversed;
Pcenterfreq = pars->Pcenterfreq;
Poctavesfreq = pars->Poctavesfreq;
Pvowelclearness = pars->Pvowelclearness;
}
/*
@@ -124,243 +128,264 @@ void FilterParams::getfromFilterParams(FilterParams *pars)
*/
REALTYPE FilterParams::getfreq()
{
return((Pfreq/64.0-1.0)*5.0);
};
return (Pfreq / 64.0 - 1.0) * 5.0;
}
REALTYPE FilterParams::getq()
{
return(exp(pow((REALTYPE) Pq/127.0,2)*log(1000.0))-0.9);
};
return exp(pow((REALTYPE) Pq / 127.0, 2) * log(1000.0)) - 0.9;
}
REALTYPE FilterParams::getfreqtracking(REALTYPE notefreq)
{
return(log(notefreq/440.0)*(Pfreqtrack-64.0)/(64.0*LOG_2));
};
return log(notefreq / 440.0) * (Pfreqtrack - 64.0) / (64.0 * LOG_2);
}
REALTYPE FilterParams::getgain()
{
return((Pgain/64.0-1.0)*30.0);//-30..30dB
};
return (Pgain / 64.0 - 1.0) * 30.0; //-30..30dB
}
/*
* Get the center frequency of the formant's graph
*/
REALTYPE FilterParams::getcenterfreq()
{
return(10000.0*pow(10,-(1.0-Pcenterfreq/127.0)*2.0));
};
return 10000.0 * pow(10, -(1.0 - Pcenterfreq / 127.0) * 2.0);
}
/*
* Get the number of octave that the formant functions applies to
*/
REALTYPE FilterParams::getoctavesfreq()
{
return(0.25+10.0*Poctavesfreq/127.0);
};
return 0.25 + 10.0 * Poctavesfreq / 127.0;
}
/*
* Get the frequency from x, where x is [0..1]
*/
REALTYPE FilterParams::getfreqx(REALTYPE x)
{
if (x>1.0) x=1.0;
REALTYPE octf=pow(2.0,getoctavesfreq());
return(getcenterfreq()/sqrt(octf)*pow(octf,x));
};
if(x > 1.0)
x = 1.0;
REALTYPE octf = pow(2.0, getoctavesfreq());
return getcenterfreq() / sqrt(octf) * pow(octf, x);
}
/*
* Get the x coordinate from frequency (used by the UI)
*/
REALTYPE FilterParams::getfreqpos(REALTYPE freq)
{
return((log(freq)-log(getfreqx(0.0)))/log(2.0)/getoctavesfreq());
};
return (log(freq) - log(getfreqx(0.0))) / log(2.0) / getoctavesfreq();
}
/*
* Get the freq. response of the formant filter
*/
void FilterParams::formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs)
void FilterParams::formantfilterH(int nvowel, int nfreqs, REALTYPE *freqs)
{
REALTYPE c[3],d[3];
REALTYPE filter_freq,filter_q,filter_amp;
REALTYPE omega,sn,cs,alpha;
REALTYPE c[3], d[3];
REALTYPE filter_freq, filter_q, filter_amp;
REALTYPE omega, sn, cs, alpha;
for (int i=0;i<nfreqs;i++) freqs[i]=0.0;
for(int i = 0; i < nfreqs; i++)
freqs[i] = 0.0;
//for each formant...
for (int nformant=0;nformant<Pnumformants;nformant++) {
for(int nformant = 0; nformant < Pnumformants; nformant++) {
//compute formant parameters(frequency,amplitude,etc.)
filter_freq=getformantfreq(Pvowels[nvowel].formants[nformant].freq);
filter_q=getformantq(Pvowels[nvowel].formants[nformant].q)*getq();
if (Pstages>0) filter_q=(filter_q>1.0 ? pow(filter_q,1.0/(Pstages+1)) : filter_q);
filter_freq = getformantfreq(Pvowels[nvowel].formants[nformant].freq);
filter_q = getformantq(Pvowels[nvowel].formants[nformant].q) * getq();
if(Pstages > 0)
filter_q =
(filter_q > 1.0 ? pow(filter_q, 1.0 / (Pstages + 1)) : filter_q);
filter_amp=getformantamp(Pvowels[nvowel].formants[nformant].amp);
filter_amp = getformantamp(Pvowels[nvowel].formants[nformant].amp);
if (filter_freq<=(SAMPLE_RATE/2-100.0)) {
omega=2*PI*filter_freq/SAMPLE_RATE;
sn=sin(omega);
cs=cos(omega);
alpha=sn/(2*filter_q);
REALTYPE tmp=1+alpha;
c[0]=alpha/tmp*sqrt(filter_q+1);
c[1]=0;
c[2]=-alpha/tmp*sqrt(filter_q+1);
d[1]=-2*cs/tmp*(-1);
d[2]=(1-alpha)/tmp*(-1);
} else continue;
if(filter_freq <= (SAMPLE_RATE / 2 - 100.0)) {
omega = 2 * PI * filter_freq / SAMPLE_RATE;
sn = sin(omega);
cs = cos(omega);
alpha = sn / (2 * filter_q);
REALTYPE tmp = 1 + alpha;
c[0] = alpha / tmp *sqrt(filter_q + 1);
c[1] = 0;
c[2] = -alpha / tmp *sqrt(filter_q + 1);
d[1] = -2 * cs / tmp * (-1);
d[2] = (1 - alpha) / tmp * (-1);
}
else
continue;
for (int i=0;i<nfreqs;i++) {
REALTYPE freq=getfreqx(i/(REALTYPE) nfreqs);
if (freq>SAMPLE_RATE/2) {
for (int tmp=i;tmp<nfreqs;tmp++) freqs[tmp]=0.0;
for(int i = 0; i < nfreqs; i++) {
REALTYPE freq = getfreqx(i / (REALTYPE) nfreqs);
if(freq > SAMPLE_RATE / 2) {
for(int tmp = i; tmp < nfreqs; tmp++)
freqs[tmp] = 0.0;
break;
};
REALTYPE fr=freq/SAMPLE_RATE*PI*2.0;
REALTYPE x=c[0],y=0.0;
for (int n=1;n<3;n++) {
x+=cos(n*fr)*c[n];
y-=sin(n*fr)*c[n];
};
REALTYPE h=x*x+y*y;
x=1.0;
y=0.0;
for (int n=1;n<3;n++) {
x-=cos(n*fr)*d[n];
y+=sin(n*fr)*d[n];
};
h=h/(x*x+y*y);
}
REALTYPE fr = freq / SAMPLE_RATE * PI * 2.0;
REALTYPE x = c[0], y = 0.0;
for(int n = 1; n < 3; n++) {
x += cos(n * fr) * c[n];
y -= sin(n * fr) * c[n];
}
REALTYPE h = x * x + y * y;
x = 1.0;
y = 0.0;
for(int n = 1; n < 3; n++) {
x -= cos(n * fr) * d[n];
y += sin(n * fr) * d[n];
}
h = h / (x * x + y * y);
freqs[i]+=pow(h,(Pstages+1.0)/2.0)*filter_amp;
};
};
for (int i=0;i<nfreqs;i++) {
if (freqs[i]>0.000000001) freqs[i]=rap2dB(freqs[i])+getgain();
else freqs[i]=-90.0;
};
};
freqs[i] += pow(h, (Pstages + 1.0) / 2.0) * filter_amp;
}
}
for(int i = 0; i < nfreqs; i++) {
if(freqs[i] > 0.000000001)
freqs[i] = rap2dB(freqs[i]) + getgain();
else
freqs[i] = -90.0;
}
}
/*
* Transforms a parameter to the real value
*/
REALTYPE FilterParams::getformantfreq(unsigned char freq)
{
REALTYPE result=getfreqx(freq/127.0);
return(result);
};
REALTYPE result = getfreqx(freq / 127.0);
return result;
}
REALTYPE FilterParams::getformantamp(unsigned char amp)
{
REALTYPE result=pow(0.1,(1.0-amp/127.0)*4.0);
return(result);
};
REALTYPE result = pow(0.1, (1.0 - amp / 127.0) * 4.0);
return result;
}
REALTYPE FilterParams::getformantq(unsigned char q)
{
//temp
REALTYPE result=pow(25.0,(q-32.0)/64.0);
return(result);
};
REALTYPE result = pow(25.0, (q - 32.0) / 64.0);
return result;
}
void FilterParams::add2XMLsection(XMLwrapper *xml,int n)
void FilterParams::add2XMLsection(XMLwrapper *xml, int n)
{
int nvowel=n;
for (int nformant=0;nformant<FF_MAX_FORMANTS;nformant++) {
xml->beginbranch("FORMANT",nformant);
xml->addpar("freq",Pvowels[nvowel].formants[nformant].freq);
xml->addpar("amp",Pvowels[nvowel].formants[nformant].amp);
xml->addpar("q",Pvowels[nvowel].formants[nformant].q);
int nvowel = n;
for(int nformant = 0; nformant < FF_MAX_FORMANTS; nformant++) {
xml->beginbranch("FORMANT", nformant);
xml->addpar("freq", Pvowels[nvowel].formants[nformant].freq);
xml->addpar("amp", Pvowels[nvowel].formants[nformant].amp);
xml->addpar("q", Pvowels[nvowel].formants[nformant].q);
xml->endbranch();
};
};
}
}
void FilterParams::add2XML(XMLwrapper *xml)
{
//filter parameters
xml->addpar("category",Pcategory);
xml->addpar("type",Ptype);
xml->addpar("freq",Pfreq);
xml->addpar("q",Pq);
xml->addpar("stages",Pstages);
xml->addpar("freq_track",Pfreqtrack);
xml->addpar("gain",Pgain);
xml->addpar("category", Pcategory);
xml->addpar("type", Ptype);
xml->addpar("freq", Pfreq);
xml->addpar("q", Pq);
xml->addpar("stages", Pstages);
xml->addpar("freq_track", Pfreqtrack);
xml->addpar("gain", Pgain);
//formant filter parameters
if ((Pcategory==1)||(!xml->minimal)) {
if((Pcategory == 1) || (!xml->minimal)) {
xml->beginbranch("FORMANT_FILTER");
xml->addpar("num_formants",Pnumformants);
xml->addpar("formant_slowness",Pformantslowness);
xml->addpar("vowel_clearness",Pvowelclearness);
xml->addpar("center_freq",Pcenterfreq);
xml->addpar("octaves_freq",Poctavesfreq);
for (int nvowel=0;nvowel<FF_MAX_VOWELS;nvowel++) {
xml->beginbranch("VOWEL",nvowel);
add2XMLsection(xml,nvowel);
xml->addpar("num_formants", Pnumformants);
xml->addpar("formant_slowness", Pformantslowness);
xml->addpar("vowel_clearness", Pvowelclearness);
xml->addpar("center_freq", Pcenterfreq);
xml->addpar("octaves_freq", Poctavesfreq);
for(int nvowel = 0; nvowel < FF_MAX_VOWELS; nvowel++) {
xml->beginbranch("VOWEL", nvowel);
add2XMLsection(xml, nvowel);
xml->endbranch();
};
xml->addpar("sequence_size",Psequencesize);
xml->addpar("sequence_stretch",Psequencestretch);
xml->addparbool("sequence_reversed",Psequencereversed);
for (int nseq=0;nseq<FF_MAX_SEQUENCE;nseq++) {
xml->beginbranch("SEQUENCE_POS",nseq);
xml->addpar("vowel_id",Psequence[nseq].nvowel);
}
xml->addpar("sequence_size", Psequencesize);
xml->addpar("sequence_stretch", Psequencestretch);
xml->addparbool("sequence_reversed", Psequencereversed);
for(int nseq = 0; nseq < FF_MAX_SEQUENCE; nseq++) {
xml->beginbranch("SEQUENCE_POS", nseq);
xml->addpar("vowel_id", Psequence[nseq].nvowel);
xml->endbranch();
};
}
xml->endbranch();
};
};
}
}
void FilterParams::getfromXMLsection(XMLwrapper *xml,int n)
void FilterParams::getfromXMLsection(XMLwrapper *xml, int n)
{
int nvowel=n;
for (int nformant=0;nformant<FF_MAX_FORMANTS;nformant++) {
if (xml->enterbranch("FORMANT",nformant)==0) continue;
Pvowels[nvowel].formants[nformant].freq=xml->getpar127("freq",Pvowels[nvowel].formants[nformant].freq);
Pvowels[nvowel].formants[nformant].amp=xml->getpar127("amp",Pvowels[nvowel].formants[nformant].amp);
Pvowels[nvowel].formants[nformant].q=xml->getpar127("q",Pvowels[nvowel].formants[nformant].q);
int nvowel = n;
for(int nformant = 0; nformant < FF_MAX_FORMANTS; nformant++) {
if(xml->enterbranch("FORMANT", nformant) == 0)
continue;
Pvowels[nvowel].formants[nformant].freq = xml->getpar127(
"freq",
Pvowels[nvowel
].formants[nformant].freq);
Pvowels[nvowel].formants[nformant].amp = xml->getpar127(
"amp",
Pvowels[nvowel
].formants[nformant].amp);
Pvowels[nvowel].formants[nformant].q =
xml->getpar127("q", Pvowels[nvowel].formants[nformant].q);
xml->exitbranch();
};
};
}
}
void FilterParams::getfromXML(XMLwrapper *xml)
{
//filter parameters
Pcategory=xml->getpar127("category",Pcategory);
Ptype=xml->getpar127("type",Ptype);
Pfreq=xml->getpar127("freq",Pfreq);
Pq=xml->getpar127("q",Pq);
Pstages=xml->getpar127("stages",Pstages);
Pfreqtrack=xml->getpar127("freq_track",Pfreqtrack);
Pgain=xml->getpar127("gain",Pgain);
Pcategory = xml->getpar127("category", Pcategory);
Ptype = xml->getpar127("type", Ptype);
Pfreq = xml->getpar127("freq", Pfreq);
Pq = xml->getpar127("q", Pq);
Pstages = xml->getpar127("stages", Pstages);
Pfreqtrack = xml->getpar127("freq_track", Pfreqtrack);
Pgain = xml->getpar127("gain", Pgain);
//formant filter parameters
if (xml->enterbranch("FORMANT_FILTER")) {
Pnumformants=xml->getpar127("num_formants",Pnumformants);
Pformantslowness=xml->getpar127("formant_slowness",Pformantslowness);
Pvowelclearness=xml->getpar127("vowel_clearness",Pvowelclearness);
Pcenterfreq=xml->getpar127("center_freq",Pcenterfreq);
Poctavesfreq=xml->getpar127("octaves_freq",Poctavesfreq);
if(xml->enterbranch("FORMANT_FILTER")) {
Pnumformants = xml->getpar127("num_formants", Pnumformants);
Pformantslowness = xml->getpar127("formant_slowness", Pformantslowness);
Pvowelclearness = xml->getpar127("vowel_clearness", Pvowelclearness);
Pcenterfreq = xml->getpar127("center_freq", Pcenterfreq);
Poctavesfreq = xml->getpar127("octaves_freq", Poctavesfreq);
for (int nvowel=0;nvowel<FF_MAX_VOWELS;nvowel++) {
if (xml->enterbranch("VOWEL",nvowel)==0) continue;
getfromXMLsection(xml,nvowel);
for(int nvowel = 0; nvowel < FF_MAX_VOWELS; nvowel++) {
if(xml->enterbranch("VOWEL", nvowel) == 0)
continue;
getfromXMLsection(xml, nvowel);
xml->exitbranch();
};
Psequencesize=xml->getpar127("sequence_size",Psequencesize);
Psequencestretch=xml->getpar127("sequence_stretch",Psequencestretch);
Psequencereversed=xml->getparbool("sequence_reversed",Psequencereversed);
for (int nseq=0;nseq<FF_MAX_SEQUENCE;nseq++) {
if (xml->enterbranch("SEQUENCE_POS",nseq)==0) continue;
Psequence[nseq].nvowel=xml->getpar("vowel_id",Psequence[nseq].nvowel,0,FF_MAX_VOWELS-1);
}
Psequencesize = xml->getpar127("sequence_size", Psequencesize);
Psequencestretch = xml->getpar127("sequence_stretch", Psequencestretch);
Psequencereversed = xml->getparbool("sequence_reversed",
Psequencereversed);
for(int nseq = 0; nseq < FF_MAX_SEQUENCE; nseq++) {
if(xml->enterbranch("SEQUENCE_POS", nseq) == 0)
continue;
Psequence[nseq].nvowel = xml->getpar("vowel_id",
Psequence[nseq].nvowel,
0,
FF_MAX_VOWELS - 1);
xml->exitbranch();
};
}
xml->exitbranch();
};
};
}
}

View File

@@ -29,72 +29,74 @@
class FilterParams:public Presets
{
public:
FilterParams(unsigned char Ptype_,unsigned char Pfreq,unsigned char Pq_);
~FilterParams();
public:
FilterParams(unsigned char Ptype_,
unsigned char Pfreq,
unsigned char Pq_);
~FilterParams();
void add2XML(XMLwrapper *xml);
void add2XMLsection(XMLwrapper *xml,int n);
void defaults();
void getfromXML(XMLwrapper *xml);
void getfromXMLsection(XMLwrapper *xml,int n);
void add2XML(XMLwrapper *xml);
void add2XMLsection(XMLwrapper *xml, int n);
void defaults();
void getfromXML(XMLwrapper *xml);
void getfromXMLsection(XMLwrapper *xml, int n);
void getfromFilterParams(FilterParams *pars);
void getfromFilterParams(FilterParams *pars);
REALTYPE getfreq();
REALTYPE getq();
REALTYPE getfreqtracking(REALTYPE notefreq);
REALTYPE getgain();
REALTYPE getfreq();
REALTYPE getq();
REALTYPE getfreqtracking(REALTYPE notefreq);
REALTYPE getgain();
unsigned char Pcategory;//Filter category (Analog/Formant/StVar)
unsigned char Ptype;// Filter type (for analog lpf,hpf,bpf..)
unsigned char Pfreq;// Frequency (64-central frequency)
unsigned char Pq; // Q parameters (resonance or bandwidth)
unsigned char Pstages; //filter stages+1
unsigned char Pfreqtrack;//how the filter frequency is changing according the note frequency
unsigned char Pgain;//filter's output gain
unsigned char Pcategory; //Filter category (Analog/Formant/StVar)
unsigned char Ptype; // Filter type (for analog lpf,hpf,bpf..)
unsigned char Pfreq; // Frequency (64-central frequency)
unsigned char Pq; // Q parameters (resonance or bandwidth)
unsigned char Pstages; //filter stages+1
unsigned char Pfreqtrack; //how the filter frequency is changing according the note frequency
unsigned char Pgain; //filter's output gain
//Formant filter parameters
unsigned char Pnumformants;//how many formants are used
unsigned char Pformantslowness;//how slow varies the formants
unsigned char Pvowelclearness;//how vowels are kept clean (how much try to avoid "mixed" vowels)
unsigned char Pcenterfreq,Poctavesfreq;//the center frequency of the res. func., and the number of octaves
//Formant filter parameters
unsigned char Pnumformants; //how many formants are used
unsigned char Pformantslowness; //how slow varies the formants
unsigned char Pvowelclearness; //how vowels are kept clean (how much try to avoid "mixed" vowels)
unsigned char Pcenterfreq, Poctavesfreq; //the center frequency of the res. func., and the number of octaves
struct {
struct {
unsigned char freq,amp,q;//frequency,amplitude,Q
}formants[FF_MAX_FORMANTS];
}Pvowels[FF_MAX_VOWELS];
struct {
unsigned char freq, amp, q; //frequency,amplitude,Q
} formants[FF_MAX_FORMANTS];
} Pvowels[FF_MAX_VOWELS];
unsigned char Psequencesize;//how many vowels are in the sequence
unsigned char Psequencestretch;//how the sequence is stretched (how the input from filter envelopes/LFOs/etc. is "stretched")
unsigned char Psequencereversed;//if the input from filter envelopes/LFOs/etc. is reversed(negated)
struct {
unsigned char nvowel;//the vowel from the position
} Psequence[FF_MAX_SEQUENCE];
unsigned char Psequencesize; //how many vowels are in the sequence
unsigned char Psequencestretch; //how the sequence is stretched (how the input from filter envelopes/LFOs/etc. is "stretched")
unsigned char Psequencereversed; //if the input from filter envelopes/LFOs/etc. is reversed(negated)
struct {
unsigned char nvowel; //the vowel from the position
} Psequence[FF_MAX_SEQUENCE];
REALTYPE getcenterfreq();
REALTYPE getoctavesfreq();
REALTYPE getfreqpos(REALTYPE freq);
REALTYPE getfreqx(REALTYPE x);
REALTYPE getcenterfreq();
REALTYPE getoctavesfreq();
REALTYPE getfreqpos(REALTYPE freq);
REALTYPE getfreqx(REALTYPE x);
void formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs);//used by UI
void formantfilterH(int nvowel, int nfreqs, REALTYPE *freqs); //used by UI
REALTYPE getformantfreq(unsigned char freq);
REALTYPE getformantamp(unsigned char amp);
REALTYPE getformantq(unsigned char q);
REALTYPE getformantfreq(unsigned char freq);
REALTYPE getformantamp(unsigned char amp);
REALTYPE getformantq(unsigned char q);
bool changed;
bool changed;
private:
void defaults(int n);
private:
void defaults(int n);
//stored default parameters
unsigned char Dtype;
unsigned char Dfreq;
unsigned char Dq;
//stored default parameters
unsigned char Dtype;
unsigned char Dfreq;
unsigned char Dq;
};
#endif

Some files were not shown because too many files have changed in this diff Show More