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:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ set(zynaddsubfx_dsp_SRCS
|
||||
Filter.cpp
|
||||
FormantFilter.cpp
|
||||
SVFilter.cpp
|
||||
Unison.cpp
|
||||
)
|
||||
|
||||
add_library(zynaddsubfx_dsp STATIC
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
192
plugins/zynaddsubfx/src/DSP/Unison.cpp
Normal file
192
plugins/zynaddsubfx/src/DSP/Unison.cpp
Normal 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;
|
||||
}
|
||||
|
||||
69
plugins/zynaddsubfx/src/DSP/Unison.h
Normal file
69
plugins/zynaddsubfx/src/DSP/Unison.h
Normal 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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_) {}
|
||||
|
||||
|
||||
@@ -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*/
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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 µ) const
|
||||
{
|
||||
return(!(*this!=micro));
|
||||
return !(*this != micro);
|
||||
}
|
||||
|
||||
bool Microtonal::operator!=(const Microtonal µ) 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 µ) 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 µ) 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 µ) const;
|
||||
bool operator!=(const Microtonal µ) const;
|
||||
//simple operators primarily for debug
|
||||
bool operator==(const Microtonal µ) const;
|
||||
bool operator!=(const Microtonal µ) 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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
{}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user