From e40fc849149dd97c248866a4a1d026dda5e57b62 Mon Sep 17 00:00:00 2001 From: Robert Jonsson Date: Mon, 7 Mar 2011 19:01:11 +0000 Subject: clean3 --- .../synti/zynaddsubfx/Synth/SUBnote.C | 419 +++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 attic/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.C (limited to 'attic/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.C') diff --git a/attic/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.C b/attic/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.C new file mode 100644 index 00000000..f198ba04 --- /dev/null +++ b/attic/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.C @@ -0,0 +1,419 @@ +/* + ZynAddSubFX - a software synthesizer + + SUBnote.C - The "subtractive" synthesizer + 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 +#include +#include +#include "../globals.h" +#include "SUBnote.h" +#include "../Misc/Util.h" + +SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote){ + ready=0; + + tmpsmp=new REALTYPE[SOUND_BUFFER_SIZE]; + tmprnd=new REALTYPE[SOUND_BUFFER_SIZE]; + + pars=parameters; + ctl=ctl_; + portamento=portamento_; + NoteEnabled=ON; + volume=pow(0.1,3.0*(1.0-pars->PVolume/96.0));//-60 dB .. 0 dB + volume*=VelF(velocity,pars->PAmpVelocityScaleFunction); + if (pars->PPanning!=0) panning=pars->PPanning/127.0; + else panning=RND; + numstages=pars->Pnumstages; + stereo=pars->Pstereo; + start=pars->Pstart; + firsttick=1; + int pos[MAX_SUB_HARMONICS]; + + if (pars->Pfixedfreq==0) basefreq=freq; + else { + basefreq=440.0; + int fixedfreqET=pars->PfixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); + else basefreq*=pow(3.0,tmp); + }; + + }; + REALTYPE detune=getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); + basefreq*=pow(2.0,detune/1200.0);//detune +// basefreq*=ctl->pitchwheel.relfreq;//pitch wheel + + //global filter + GlobalFilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq + (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing + (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); + + GlobalFilterL=NULL;GlobalFilterR=NULL; + GlobalFilterEnvelope=NULL; + + //select only harmonics that desire to compute + numharmonics=0; + for (int n=0;nPhmag[n]==0)continue; + if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq + pos[numharmonics++]=n; + }; + + if (numharmonics==0) { + NoteEnabled=OFF; + return; + }; + + + lfilter=new bpfilter[numstages*numharmonics]; + if (stereo!=0) rfilter=new bpfilter[numstages*numharmonics]; + + //how much the amplitude is normalised (because the harmonics) + REALTYPE reduceamp=0.0; + + for (int n=0;nPbandwidth-127.0)/127.0*4)*numstages; + + //Bandwidth Scale + bw*=pow(1000/freq,(pars->Pbwscale-64.0)/64.0*3.0); + + //Relative BandWidth + bw*=pow(100,(pars->Phrelbw[pos[n]]-64.0)/64.0); + + if (bw>25.0) bw=25.0; + + //try to keep same amplitude on all freqs and bw. (empirically) + REALTYPE gain=sqrt(1500.0/(bw*freq)); + + REALTYPE hmagnew=1.0-pars->Phmag[pos[n]]/127.0; + REALTYPE hgain; + + switch(pars->Phmagtype){ + case 1:hgain=exp(hmagnew*log(0.01)); break; + case 2:hgain=exp(hmagnew*log(0.001));break; + case 3:hgain=exp(hmagnew*log(0.0001));break; + case 4:hgain=exp(hmagnew*log(0.00001));break; + default:hgain=1.0-hmagnew; + }; + gain*=hgain; + reduceamp+=hgain; + + for (int nph=0;nphPfixedfreq==0) initparameters(basefreq); + else initparameters(basefreq/440.0*freq); + + oldamplitude=newamplitude; + ready=1; +}; + +SUBnote::~SUBnote(){ + if (NoteEnabled!=OFF) KillNote(); + delete [] tmpsmp; + delete [] tmprnd; +}; + +/* + * Kill the note + */ +void SUBnote::KillNote(){ + if (NoteEnabled!=OFF){ + delete [] lfilter; + lfilter=NULL; + if (stereo!=0) delete [] rfilter; + rfilter=NULL; + delete(AmpEnvelope); + if (FreqEnvelope!=NULL) delete(FreqEnvelope); + if (BandWidthEnvelope!=NULL) delete(BandWidthEnvelope); + NoteEnabled=OFF; + }; + +}; + + +/* + * Compute the filters coefficients + */ +void SUBnote::computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain){ + if (freq>SAMPLE_RATE/2.0-200.0) { + freq=SAMPLE_RATE/2.0-200.0; + }; + + REALTYPE omega=2.0*PI*freq/SAMPLE_RATE; + REALTYPE sn=sin(omega);REALTYPE cs=cos(omega); + REALTYPE alpha=sn*sinh(LOG_2/2.0*bw*omega/sn); + + if (alpha>1) alpha=1; + if (alpha>bw) alpha=bw; + + filter.b0=alpha/(1.0+alpha)*filter.amp*gain; + filter.b2=-alpha/(1.0+alpha)*filter.amp*gain; + filter.a1=-2.0*cs/(1.0+alpha); + filter.a2=(1.0-alpha)/(1.0+alpha); + +}; + + +/* + * Initialise the filters + */ +void SUBnote::initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag){ + filter.xn1=0.0;filter.xn2=0.0; + + if (start==0) { + filter.yn1=0.0; + filter.yn2=0.0; + } else { + REALTYPE a=0.1*mag;//empirically + REALTYPE p=RND*2.0*PI; + if (start==1) a*=RND; + filter.yn1=a*cos(p); + filter.yn2=a*cos(p+freq*2.0*PI/SAMPLE_RATE); + + //correct the error of computation the start amplitude + //at very high frequencies + if (freq>SAMPLE_RATE*0.96) { + filter.yn1=0.0; + filter.yn2=0.0; + + }; + }; + + filter.amp=amp; + filter.freq=freq; + filter.bw=bw; + computefiltercoefs(filter,freq,bw,1.0); +}; + +/* + * Do the filtering + */ +void SUBnote::filter(bpfilter &filter,REALTYPE *smps){ + int i; + REALTYPE out; + for (i=0;iAmpEnvelope,freq); + if (pars->PFreqEnvelopeEnabled!=0) FreqEnvelope=new Envelope(pars->FreqEnvelope,freq); + else FreqEnvelope=NULL; + if (pars->PBandWidthEnvelopeEnabled!=0) BandWidthEnvelope=new Envelope(pars->BandWidthEnvelope,freq); + else BandWidthEnvelope=NULL; + if (pars->PGlobalFilterEnabled!=0){ + globalfiltercenterq=pars->GlobalFilter->getq(); + GlobalFilterL=new Filter(pars->GlobalFilter); + if (stereo!=0) GlobalFilterR=new Filter(pars->GlobalFilter); + GlobalFilterEnvelope=new Envelope(pars->GlobalFilterEnvelope,freq); + GlobalFilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); + }; + computecurrentparameters(); +}; + + +/* + * Compute Parameters of SUBnote for each tick + */ +void SUBnote::computecurrentparameters(){ + if ((FreqEnvelope!=NULL)||(BandWidthEnvelope!=NULL)|| + (oldpitchwheel!=ctl->pitchwheel.data)|| + (oldbandwidth!=ctl->bandwidth.data)|| + (portamento!=0)){ + REALTYPE envfreq=1.0; + REALTYPE envbw=1.0; + REALTYPE gain=1.0; + + if (FreqEnvelope!=NULL) { + envfreq=FreqEnvelope->envout()/1200; + envfreq=pow(2.0,envfreq); + }; + envfreq*=ctl->pitchwheel.relfreq;//pitch wheel + if (portamento!=0) {//portamento is used + envfreq*=ctl->portamento.freqrap; + if (ctl->portamento.used==0){//the portamento has finished + portamento=0;//this note is no longer "portamented" + }; + }; + + if (BandWidthEnvelope!=NULL) { + envbw=BandWidthEnvelope->envout(); + envbw=pow(2,envbw); + }; + envbw*=ctl->bandwidth.relbw;//bandwidth controller + + REALTYPE tmpgain=1.0/sqrt(envbw*envfreq); + + for (int n=0;nbandwidth.data; + oldpitchwheel=ctl->pitchwheel.data; + }; + newamplitude=volume*AmpEnvelope->envout_dB()*2.0; + + //Filter + if (GlobalFilterL!=NULL){ + REALTYPE globalfilterpitch=GlobalFilterCenterPitch+GlobalFilterEnvelope->envout(); + REALTYPE filterfreq=globalfilterpitch+ctl->filtercutoff.relfreq+GlobalFilterFreqTracking; + filterfreq=GlobalFilterL->getrealfreq(filterfreq); + + GlobalFilterL->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); + if (GlobalFilterR!=NULL) GlobalFilterR->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); + }; + +}; + +/* + * Note Output + */ +int SUBnote::noteout(REALTYPE *outl,REALTYPE *outr){ + int i; + + for (i=0;ifilterout(&outl[0]); + + //right channel + if (stereo!=0){ + for (i=0;ifilterout(&outr[0]); + } else for (i=0;iSOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; + for (i=0;ifinished()!=0){ + for (i=0;irelasekey(); + if (FreqEnvelope!=NULL) FreqEnvelope->relasekey(); + if (BandWidthEnvelope!=NULL) BandWidthEnvelope->relasekey(); + if (GlobalFilterEnvelope!=NULL) GlobalFilterEnvelope->relasekey(); +}; + +/* + * Check if the note is finished + */ +int SUBnote::finished(){ + if (NoteEnabled==OFF) return(1); + else return(0); +}; + -- cgit v1.2.3