diff options
Diffstat (limited to 'muse_qt4_evolution/synti/zynaddsubfx/DSP')
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/AnalogFilter.C | 358 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/AnalogFilter.h | 72 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/FFTwrapper.C | 99 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/FFTwrapper.h | 59 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter.C | 72 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter.h | 51 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter_.h | 42 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/FormantFilter.C | 163 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/FormantFilter.h | 67 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/SVFilter.C | 152 | ||||
-rw-r--r-- | muse_qt4_evolution/synti/zynaddsubfx/DSP/SVFilter.h | 67 |
11 files changed, 1202 insertions, 0 deletions
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/AnalogFilter.C b/muse_qt4_evolution/synti/zynaddsubfx/DSP/AnalogFilter.C new file mode 100644 index 00000000..5e461a0b --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/AnalogFilter.C @@ -0,0 +1,358 @@ +/* + ZynAddSubFX - a software synthesizer + + AnalogFilter.C - Several analog filters (lowpass, highpass...) + 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) 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 "AnalogFilter.h" + +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; + cleanup(); + 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; +}; + +void AnalogFilter::computefiltercoefs(){ + REALTYPE tmp; + 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; + //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)); + }; + + //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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + + 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; + + 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; + 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; + + oldabovenq=abovenq;abovenq=frequency>(SAMPLE_RATE/2-500.0); + + 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; + computefiltercoefs(); + firsttime=0; + +}; + +void AnalogFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){ + q=q_; + setfreq(frequency); +}; + +void AnalogFilter::setq(REALTYPE q_){ + q=q_; + computefiltercoefs(); +}; + +void AnalogFilter::settype(int type_){ + type=type_; + computefiltercoefs(); +}; + +void AnalogFilter::setgain(REALTYPE dBgain){ + gain=dB2rap(dBgain); + computefiltercoefs(); +}; + +void AnalogFilter::setstages(int 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){ + 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]; + //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]; + //output + smp[i]=y0; + }; + }; +}; +void AnalogFilter::filterout(REALTYPE *smp){ + 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); + }; + + 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; + }; + delete (ismp); + needsinterpolation=0; + }; + + 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)); +}; + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/AnalogFilter.h b/muse_qt4_evolution/synti/zynaddsubfx/DSP/AnalogFilter.h new file mode 100644 index 00000000..2e9fe68b --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/AnalogFilter.h @@ -0,0 +1,72 @@ +/* + ZynAddSubFX - a software synthesizer + + Analog Filter.h - Several analog filters (lowpass, highpass...) + 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) 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 ANALOG_FILTER_H +#define ANALOG_FILTER_H + +#include "../globals.h" +#include "Filter_.h" +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_); + + 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 + + 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 + + int order;//the order of the filter (number of poles) + + 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 xd[3],yd[3];//used if the filter is applied more times + int needsinterpolation,firsttime; + 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) +}; + + +#endif + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/FFTwrapper.C b/muse_qt4_evolution/synti/zynaddsubfx/DSP/FFTwrapper.C new file mode 100644 index 00000000..7c67e631 --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/FFTwrapper.C @@ -0,0 +1,99 @@ +/* + ZynAddSubFX - a software synthesizer + + FFTwrapper.c - A wrapper for Fast Fourier Transforms + 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) 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 "FFTwrapper.h" + +FFTwrapper::FFTwrapper(int 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); +#else + planfftw=fftw_plan_r2r_1d(fftsize,tmpfftdata1,tmpfftdata1,FFTW_R2HC,FFTW_ESTIMATE); + planfftw_inv=fftw_plan_r2r_1d(fftsize,tmpfftdata2,tmpfftdata2,FFTW_HC2R,FFTW_ESTIMATE); +#endif +}; + +FFTwrapper::~FFTwrapper(){ +#ifdef FFTW_VERSION_2 + rfftw_destroy_plan(planfftw); + rfftw_destroy_plan(planfftw_inv); +#else + fftw_destroy_plan(planfftw); + fftw_destroy_plan(planfftw_inv); +#endif + + delete [] tmpfftdata1; + delete [] tmpfftdata2; +}; + +/* + * do the Fast Fourier Transform + */ +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]; + }; +#else + for (int i=0;i<fftsize;i++) tmpfftdata1[i]=smps[i]; + fftw_execute(planfftw); + 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; +}; + +/* + * do the Inverse Fast Fourier Transform + */ +void FFTwrapper::freqs2smps(FFTFREQS freqs,REALTYPE *smps){ + 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]; +#else + for (int i=0;i<fftsize/2;i++) { + tmpfftdata2[i]=freqs.c[i]; + if (i!=0) tmpfftdata2[fftsize-i]=freqs.s[i]; + }; + fftw_execute(planfftw_inv); + for (int i=0;i<fftsize;i++) smps[i]=tmpfftdata2[i]; +#endif + +}; + + + + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/FFTwrapper.h b/muse_qt4_evolution/synti/zynaddsubfx/DSP/FFTwrapper.h new file mode 100644 index 00000000..df8cad7a --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/FFTwrapper.h @@ -0,0 +1,59 @@ +/* + ZynAddSubFX - a software synthesizer + + FFTwrapper.h - A wrapper for Fast Fourier Transforms + 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) 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 FFT_WRAPPER_H +#define FFT_WRAPPER_H + +#include "../globals.h" + +#ifdef FFTW_VERSION_2 + +#include <fftw.h> + +/* If you got error messages about rfftw.h, replace the next include line with "#include <srfftw.h>" +or with "#include <drfftw.h> (if one doesn't work try the other). It may be necessary to replace +the <fftw.h> with <dfftw.h> or <sfftw.h>. If the neither one doesn't work, +please install latest version of fftw(recomanded from the sources) from www.fftw.org. +If you'll install fftw3 you need to change the Makefile.inc +Hope all goes right." */ +#include <rfftw.h> + +#else + +#include <fftw3.h> +#define fftw_real double +#define rfftw_plan fftw_plan +#endif + +class FFTwrapper{ + public: + FFTwrapper(int fftsize_); + ~FFTwrapper(); + void smps2freqs(REALTYPE *smps,FFTFREQS freqs); + void freqs2smps(FFTFREQS freqs,REALTYPE *smps); + private: + int fftsize; + fftw_real *tmpfftdata1,*tmpfftdata2; + rfftw_plan planfftw,planfftw_inv; +}; +#endif + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter.C b/muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter.C new file mode 100644 index 00000000..fccb0265 --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter.C @@ -0,0 +1,72 @@ +/* + ZynAddSubFX - a software synthesizer + + Filter.C - Filters, uses analog,formant,etc. filters + 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) 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 "Filter.h" + +Filter::Filter(FilterParams *pars){ + unsigned char Ftype=pars->Ptype; + unsigned char Fstages=pars->Pstages; + + category=pars->Pcategory; + + switch (category) { + case 1: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); + 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()); + 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_){ + 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); +}; + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter.h b/muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter.h new file mode 100644 index 00000000..dab948c1 --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter.h @@ -0,0 +1,51 @@ +/* + ZynAddSubFX - a software synthesizer + + Filter.h - Filters, uses analog,formant,etc. filters + 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) 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 FILTER_H +#define FILTER_H + +#include "../globals.h" + +#include "Filter_.h" +#include "AnalogFilter.h" +#include "FormantFilter.h" +#include "SVFilter.h" +#include "../Params/FilterParams.h" + +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_); + + REALTYPE getrealfreq(REALTYPE freqpitch); + private: + Filter_ *filter; + unsigned char category; +}; + + +#endif + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter_.h b/muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter_.h new file mode 100644 index 00000000..66fff867 --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/Filter_.h @@ -0,0 +1,42 @@ +/* + ZynAddSubFX - a software synthesizer + + Filter_.h - This class is inherited by filter classes + 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) 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 FILTER__H +#define FILTER__H + +#include "../globals.h" + +class Filter_{ + public: + virtual ~Filter_(){}; + virtual void filterout(REALTYPE */*smp*/){}; + virtual void setfreq(REALTYPE /*frequency*/){}; + virtual void setfreq_and_q(REALTYPE /*frequency*/,REALTYPE /*q_*/){}; + virtual void setq(REALTYPE /*q_*/){}; + virtual void setgain(REALTYPE /*dBgain*/){}; + REALTYPE outgain; + private: +}; + + +#endif + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/FormantFilter.C b/muse_qt4_evolution/synti/zynaddsubfx/DSP/FormantFilter.C new file mode 100644 index 00000000..482cef91 --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/FormantFilter.C @@ -0,0 +1,163 @@ +/* + ZynAddSubFX - a software synthesizer + + FormantFilter.C - formant filters + 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) 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 "FormantFilter.h" + +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); + cleanup(); + 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; + }; + + 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; + + 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; + + outgain=dB2rap(pars->getgain()); + + oldinput=-1.0; + Qfactor=1.0;oldQfactor=Qfactor; + firsttime=1; +}; + +FormantFilter::~FormantFilter(){ + 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(); +}; + +void FormantFilter::setpos(REALTYPE input){ + int p1,p2; + + 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)) { +// oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente + firsttime=0; + return; + } else oldinput=input; + + + 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; + + 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; + + 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].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); + }; + }; + + 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); +}; + +void FormantFilter::setfreq_and_q(REALTYPE frequency,REALTYPE 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; + }; + + 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; + }; +}; + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/FormantFilter.h b/muse_qt4_evolution/synti/zynaddsubfx/DSP/FormantFilter.h new file mode 100644 index 00000000..7cb52499 --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/FormantFilter.h @@ -0,0 +1,67 @@ +/* + ZynAddSubFX - a software synthesizer + + FormantFilter.h - formant filter + 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) 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 FORMANT_FILTER_H +#define FORMANT_FILTER_H + +#include "../globals.h" +#include "Filter_.h" +#include "AnalogFilter.h" +#include "../Params/FilterParams.h" + + +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_); + + 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 { + unsigned char nvowel; + } sequence [FF_MAX_SEQUENCE]; + + REALTYPE oldformantamp[FF_MAX_FORMANTS]; + + int sequencesize,numformants,firsttime; + REALTYPE oldinput,slowinput; + REALTYPE Qfactor,formantslowness,oldQfactor; + REALTYPE vowelclearness,sequencestretch; + + void setpos(REALTYPE input); + +}; + + +#endif + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/SVFilter.C b/muse_qt4_evolution/synti/zynaddsubfx/DSP/SVFilter.C new file mode 100644 index 00000000..8c0e16b2 --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/SVFilter.C @@ -0,0 +1,152 @@ +/* + ZynAddSubFX - a software synthesizer + + SVFilter.C - Several state-variable filters + 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) 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 "SVFilter.h" + +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; + cleanup(); + 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; +}; + +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); +}; + + +void SVFilter::setfreq(REALTYPE frequency){ + 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); + + 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; + computefiltercoefs(); + firsttime=0; + +}; + +void SVFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){ + q=q_; + setfreq(frequency); +}; + +void SVFilter::setq(REALTYPE q_){ + q=q_; + computefiltercoefs(); +}; + +void SVFilter::settype(int type_){ + type=type_; + computefiltercoefs(); +}; + +void SVFilter::setgain(REALTYPE dBgain){ + gain=dB2rap(dBgain); + computefiltercoefs(); +}; + +void SVFilter::setstages(int stages_){ + if (stages_>=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1; + stages=stages_; + cleanup(); + computefiltercoefs(); +}; + +void SVFilter::singlefilterout(REALTYPE *smp,fstage &x,parameters &par){ + int i; + REALTYPE *out=NULL; + switch(type){ + case 0: out=&x.low;break; + case 1: out=&x.high;break; + case 2: out=&x.band;break; + case 3: 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; + x.notch = x.high + x.low; + + smp[i]= *out; + }; +}; + +void SVFilter::filterout(REALTYPE *smp){ + int i; + 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); + }; + + 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; + }; + delete (ismp); + needsinterpolation=0; + }; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]*=outgain; + +}; + diff --git a/muse_qt4_evolution/synti/zynaddsubfx/DSP/SVFilter.h b/muse_qt4_evolution/synti/zynaddsubfx/DSP/SVFilter.h new file mode 100644 index 00000000..3117e2c9 --- /dev/null +++ b/muse_qt4_evolution/synti/zynaddsubfx/DSP/SVFilter.h @@ -0,0 +1,67 @@ +/* + ZynAddSubFX - a software synthesizer + + SV Filter.h - Several state-variable filters + 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) 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 SV_FILTER_H +#define SV_FILTER_H + +#include "../globals.h" +#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_); + + 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]; + + 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 + + int abovenq;//this is 1 if the frequency is above the nyquist + int oldabovenq; + int needsinterpolation,firsttime; +}; + + +#endif + |