summaryrefslogtreecommitdiff
path: root/muse_qt4_evolution/synti/zynaddsubfx/Synth
diff options
context:
space:
mode:
Diffstat (limited to 'muse_qt4_evolution/synti/zynaddsubfx/Synth')
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C984
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.h258
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/Envelope.C165
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/Envelope.h58
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/LFO.C145
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/LFO.h52
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/OscilGen.C1182
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/OscilGen.h176
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/PADnote.C342
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/PADnote.h106
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/Resonance.C231
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/Resonance.h68
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.C419
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.h98
14 files changed, 4284 insertions, 0 deletions
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C b/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C
new file mode 100644
index 00000000..574e2bea
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.C
@@ -0,0 +1,984 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ ADnote.C - The "additive" 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 <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#include "../globals.h"
+#include "../Misc/Util.h"
+#include "ADnote.h"
+
+
+ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_){
+ ready=0;
+
+ tmpwave=new REALTYPE [SOUND_BUFFER_SIZE];
+ bypassl=new REALTYPE [SOUND_BUFFER_SIZE];
+ bypassr=new REALTYPE [SOUND_BUFFER_SIZE];
+
+ partparams=pars;
+ ctl=ctl_;
+ portamento=portamento_;
+ midinote=midinote_;
+ NoteEnabled=ON;
+ basefreq=freq;
+ if (velocity>1.0) velocity=1.0;
+ this->velocity=velocity;
+ time=0.0;
+ stereo=pars->GlobalPar.PStereo;
+
+ NoteGlobalPar.Detune=getdetune(pars->GlobalPar.PDetuneType
+ ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune);
+ bandwidthDetuneMultiplier=pars->getBandwidthDetuneMultiplier();
+
+ if (pars->GlobalPar.PPanning==0) NoteGlobalPar.Panning=RND;
+ else NoteGlobalPar.Panning=pars->GlobalPar.PPanning/128.0;
+
+
+ NoteGlobalPar.FilterCenterPitch=pars->GlobalPar.GlobalFilter->getfreq()+//center freq
+ pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing
+ (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1);
+
+ if (pars->GlobalPar.PPunchStrength!=0) {
+ NoteGlobalPar.Punch.Enabled=1;
+ NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0
+ NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->GlobalPar.PPunchStrength/127.0)-1.0)
+ *VelF(velocity,pars->GlobalPar.PPunchVelocitySensing) );
+ REALTYPE time=pow(10,3.0*pars->GlobalPar.PPunchTime/127.0)/10000.0;//0.1 .. 100 ms
+ REALTYPE stretch=pow(440.0/freq,pars->GlobalPar.PPunchStretch/64.0);
+ NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch);
+ } else NoteGlobalPar.Punch.Enabled=0;
+
+ for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ pars->VoicePar[nvoice].OscilSmp->newrandseed(rand());
+ NoteVoicePar[nvoice].OscilSmp=NULL;
+ NoteVoicePar[nvoice].FMSmp=NULL;
+ NoteVoicePar[nvoice].VoiceOut=NULL;
+
+ NoteVoicePar[nvoice].FMVoice=-1;
+
+ if (pars->VoicePar[nvoice].Enabled==0) {
+ NoteVoicePar[nvoice].Enabled=OFF;
+ continue; //the voice is disabled
+ };
+
+ NoteVoicePar[nvoice].Enabled=ON;
+ NoteVoicePar[nvoice].fixedfreq=pars->VoicePar[nvoice].Pfixedfreq;
+ NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET;
+
+ //use the Globalpars.detunetype if the detunetype is 0
+ if (pars->VoicePar[nvoice].PDetuneType!=0){
+ NoteVoicePar[nvoice].Detune=getdetune(pars->VoicePar[nvoice].PDetuneType
+ ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune
+ NoteVoicePar[nvoice].FineDetune=getdetune(pars->VoicePar[nvoice].PDetuneType
+ ,0,pars->VoicePar[nvoice].PDetune);//fine detune
+ } else {
+ NoteVoicePar[nvoice].Detune=getdetune(pars->GlobalPar.PDetuneType
+ ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune
+ NoteVoicePar[nvoice].FineDetune=getdetune(pars->GlobalPar.PDetuneType
+ ,0,pars->VoicePar[nvoice].PDetune);//fine detune
+ };
+ if (pars->VoicePar[nvoice].PFMDetuneType!=0){
+ NoteVoicePar[nvoice].FMDetune=getdetune(pars->VoicePar[nvoice].PFMDetuneType
+ ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune);
+ } else {
+ NoteVoicePar[nvoice].FMDetune=getdetune(pars->GlobalPar.PDetuneType
+ ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune);
+ };
+
+ oscposhi[nvoice]=0;oscposlo[nvoice]=0.0;
+ oscposhiFM[nvoice]=0;oscposloFM[nvoice]=0.0;
+
+ NoteVoicePar[nvoice].OscilSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES];//the extra points contains the first point
+
+ //Get the voice's oscil or external's voice oscil
+ int vc=nvoice;
+ if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil;
+ if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand());
+ oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),
+ pars->VoicePar[nvoice].Presonance);
+
+ //I store the first elments to the last position for speedups
+ for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].OscilSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].OscilSmp[i];
+
+ oscposhi[nvoice]+=(int)((pars->VoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4);
+ oscposhi[nvoice]%=OSCIL_SIZE;
+
+
+ NoteVoicePar[nvoice].FreqLfo=NULL;
+ NoteVoicePar[nvoice].FreqEnvelope=NULL;
+
+ NoteVoicePar[nvoice].AmpLfo=NULL;
+ NoteVoicePar[nvoice].AmpEnvelope=NULL;
+
+ NoteVoicePar[nvoice].VoiceFilter=NULL;
+ NoteVoicePar[nvoice].FilterEnvelope=NULL;
+ NoteVoicePar[nvoice].FilterLfo=NULL;
+
+ NoteVoicePar[nvoice].FilterCenterPitch=pars->VoicePar[nvoice].VoiceFilter->getfreq();
+ NoteVoicePar[nvoice].filterbypass=pars->VoicePar[nvoice].Pfilterbypass;
+
+ switch(pars->VoicePar[nvoice].PFMEnabled){
+ case 1:NoteVoicePar[nvoice].FMEnabled=MORPH;break;
+ case 2:NoteVoicePar[nvoice].FMEnabled=RING_MOD;break;
+ case 3:NoteVoicePar[nvoice].FMEnabled=PHASE_MOD;break;
+ case 4:NoteVoicePar[nvoice].FMEnabled=FREQ_MOD;break;
+ case 5:NoteVoicePar[nvoice].FMEnabled=PITCH_MOD;break;
+ default:NoteVoicePar[nvoice].FMEnabled=NONE;
+ };
+
+ NoteVoicePar[nvoice].FMVoice=pars->VoicePar[nvoice].PFMVoice;
+ NoteVoicePar[nvoice].FMFreqEnvelope=NULL;
+ NoteVoicePar[nvoice].FMAmpEnvelope=NULL;
+
+ //Compute the Voice's modulator volume (incl. damping)
+ REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0);
+ switch (NoteVoicePar[nvoice].FMEnabled){
+ case PHASE_MOD:fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0);
+ NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0;
+ break;
+ case FREQ_MOD:NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0;
+ break;
+ // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//???????????
+ // break;
+ default:if (fmvoldamp>1.0) fmvoldamp=1.0;
+ NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp;
+ };
+
+ //Voice's modulator velocity sensing
+ NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction);
+
+ FMoldsmp[nvoice]=0.0;//this is for FM (integration)
+
+ firsttick[nvoice]=1;
+ NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE);
+ };
+
+ initparameters();
+ ready=1;
+};
+
+
+/*
+ * Kill a voice of ADnote
+ */
+void ADnote::KillVoice(int nvoice){
+
+ delete (NoteVoicePar[nvoice].OscilSmp);
+
+ if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) delete(NoteVoicePar[nvoice].FreqEnvelope);
+ NoteVoicePar[nvoice].FreqEnvelope=NULL;
+
+ if (NoteVoicePar[nvoice].FreqLfo!=NULL) delete(NoteVoicePar[nvoice].FreqLfo);
+ NoteVoicePar[nvoice].FreqLfo=NULL;
+
+ if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) delete (NoteVoicePar[nvoice].AmpEnvelope);
+ NoteVoicePar[nvoice].AmpEnvelope=NULL;
+
+ if (NoteVoicePar[nvoice].AmpLfo!=NULL) delete (NoteVoicePar[nvoice].AmpLfo);
+ NoteVoicePar[nvoice].AmpLfo=NULL;
+
+ if (NoteVoicePar[nvoice].VoiceFilter!=NULL) delete (NoteVoicePar[nvoice].VoiceFilter);
+ NoteVoicePar[nvoice].VoiceFilter=NULL;
+
+ if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) delete (NoteVoicePar[nvoice].FilterEnvelope);
+ NoteVoicePar[nvoice].FilterEnvelope=NULL;
+
+ if (NoteVoicePar[nvoice].FilterLfo!=NULL) delete (NoteVoicePar[nvoice].FilterLfo);
+ NoteVoicePar[nvoice].FilterLfo=NULL;
+
+ if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) delete (NoteVoicePar[nvoice].FMFreqEnvelope);
+ NoteVoicePar[nvoice].FMFreqEnvelope=NULL;
+
+ if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) delete (NoteVoicePar[nvoice].FMAmpEnvelope);
+ NoteVoicePar[nvoice].FMAmpEnvelope=NULL;
+
+ if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)) delete NoteVoicePar[nvoice].FMSmp;
+
+ if (NoteVoicePar[nvoice].VoiceOut!=NULL)
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0;//do not delete, yet: perhaps is used by another voice
+
+ NoteVoicePar[nvoice].Enabled=OFF;
+};
+
+/*
+ * Kill the note
+ */
+void ADnote::KillNote(){
+ int nvoice;
+ for (nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ if (NoteVoicePar[nvoice].Enabled==ON) KillVoice(nvoice);
+
+ //delete VoiceOut
+ if (NoteVoicePar[nvoice].VoiceOut!=NULL) delete(NoteVoicePar[nvoice].VoiceOut);
+ NoteVoicePar[nvoice].VoiceOut=NULL;
+ };
+
+ delete (NoteGlobalPar.FreqEnvelope);
+ delete (NoteGlobalPar.FreqLfo);
+ delete (NoteGlobalPar.AmpEnvelope);
+ delete (NoteGlobalPar.AmpLfo);
+ delete (NoteGlobalPar.GlobalFilterL);
+ if (stereo!=0) delete (NoteGlobalPar.GlobalFilterR);
+ delete (NoteGlobalPar.FilterEnvelope);
+ delete (NoteGlobalPar.FilterLfo);
+
+ NoteEnabled=OFF;
+};
+
+ADnote::~ADnote(){
+ if (NoteEnabled==ON) KillNote();
+ delete [] tmpwave;
+ delete [] bypassl;
+ delete [] bypassr;
+};
+
+
+/*
+ * Init the parameters
+ */
+void ADnote::initparameters(){
+ int nvoice,i,tmp[NUM_VOICES];
+
+ // Global Parameters
+ NoteGlobalPar.FreqEnvelope=new Envelope(partparams->GlobalPar.FreqEnvelope,basefreq);
+ NoteGlobalPar.FreqLfo=new LFO(partparams->GlobalPar.FreqLfo,basefreq);
+
+ NoteGlobalPar.AmpEnvelope=new Envelope(partparams->GlobalPar.AmpEnvelope,basefreq);
+ NoteGlobalPar.AmpLfo=new LFO(partparams->GlobalPar.AmpLfo,basefreq);
+
+ NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-partparams->GlobalPar.PVolume/96.0))//-60 dB .. 0 dB
+ *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing
+
+ NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output
+ globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout();
+
+ NoteGlobalPar.GlobalFilterL=new Filter(partparams->GlobalPar.GlobalFilter);
+ if (stereo!=0) NoteGlobalPar.GlobalFilterR=new Filter(partparams->GlobalPar.GlobalFilter);
+
+ NoteGlobalPar.FilterEnvelope=new Envelope(partparams->GlobalPar.FilterEnvelope,basefreq);
+ NoteGlobalPar.FilterLfo=new LFO(partparams->GlobalPar.FilterLfo,basefreq);
+ NoteGlobalPar.FilterQ=partparams->GlobalPar.GlobalFilter->getq();
+ NoteGlobalPar.FilterFreqTracking=partparams->GlobalPar.GlobalFilter->getfreqtracking(basefreq);
+
+ // Forbids the Modulation Voice to be greater or equal than voice
+ for (i=0;i<NUM_VOICES;i++) if (NoteVoicePar[i].FMVoice>=i) NoteVoicePar[i].FMVoice=-1;
+
+ // Voice Parameter init
+ for (nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ if (NoteVoicePar[nvoice].Enabled==0) continue;
+
+ NoteVoicePar[nvoice].noisetype=partparams->VoicePar[nvoice].Type;
+ /* Voice Amplitude Parameters Init */
+ NoteVoicePar[nvoice].Volume=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -60 dB .. 0 dB
+ *VelF(velocity,partparams->VoicePar[nvoice].PAmpVelocityScaleFunction);//velocity
+
+ if (partparams->VoicePar[nvoice].PVolumeminus!=0) NoteVoicePar[nvoice].Volume=-NoteVoicePar[nvoice].Volume;
+
+ if (partparams->VoicePar[nvoice].PPanning==0)
+ NoteVoicePar[nvoice].Panning=RND;// random panning
+ else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0;
+
+ newamplitude[nvoice]=1.0;
+ if (partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) {
+ NoteVoicePar[nvoice].AmpEnvelope=new Envelope(partparams->VoicePar[nvoice].AmpEnvelope,basefreq);
+ NoteVoicePar[nvoice].AmpEnvelope->envout_dB();//discard the first envelope sample
+ newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB();
+ };
+
+ if (partparams->VoicePar[nvoice].PAmpLfoEnabled!=0){
+ NoteVoicePar[nvoice].AmpLfo=new LFO(partparams->VoicePar[nvoice].AmpLfo,basefreq);
+ newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout();
+ };
+
+ /* Voice Frequency Parameters Init */
+ if (partparams->VoicePar[nvoice].PFreqEnvelopeEnabled!=0)
+ NoteVoicePar[nvoice].FreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FreqEnvelope,basefreq);
+
+ if (partparams->VoicePar[nvoice].PFreqLfoEnabled!=0) NoteVoicePar[nvoice].FreqLfo=new LFO(partparams->VoicePar[nvoice].FreqLfo,basefreq);
+
+ /* Voice Filter Parameters Init */
+ if (partparams->VoicePar[nvoice].PFilterEnabled!=0){
+ NoteVoicePar[nvoice].VoiceFilter=new Filter(partparams->VoicePar[nvoice].VoiceFilter);
+ };
+
+ if (partparams->VoicePar[nvoice].PFilterEnvelopeEnabled!=0)
+ NoteVoicePar[nvoice].FilterEnvelope=new Envelope(partparams->VoicePar[nvoice].FilterEnvelope,basefreq);
+
+ if (partparams->VoicePar[nvoice].PFilterLfoEnabled!=0)
+ NoteVoicePar[nvoice].FilterLfo=new LFO(partparams->VoicePar[nvoice].FilterLfo,basefreq);
+
+ NoteVoicePar[nvoice].FilterFreqTracking=partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq);
+
+ /* Voice Modulation Parameters Init */
+ if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)){
+ partparams->VoicePar[nvoice].FMSmp->newrandseed(rand());
+ NoteVoicePar[nvoice].FMSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES];
+
+ //Perform Anti-aliasing only on MORPH or RING MODULATION
+
+ int vc=nvoice;
+ if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil;
+
+ REALTYPE tmp=1.0;
+ if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)||
+ (NoteVoicePar[nvoice].FMEnabled==MORPH)||
+ (NoteVoicePar[nvoice].FMEnabled==RING_MOD)){
+ tmp=getFMvoicebasefreq(nvoice);
+ };
+ if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand());
+
+ oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE;
+ for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].FMSmp[i];
+ oscposhiFM[nvoice]+=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4);
+ oscposhiFM[nvoice]%=OSCIL_SIZE;
+ };
+
+ if (partparams->VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0)
+ NoteVoicePar[nvoice].FMFreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FMFreqEnvelope,basefreq);
+
+ FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp;
+
+ if (partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0){
+ NoteVoicePar[nvoice].FMAmpEnvelope=new Envelope(partparams->VoicePar[nvoice].FMAmpEnvelope,basefreq);
+ FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB();
+ };
+ };
+
+ for (nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ for (i=nvoice+1;i<NUM_VOICES;i++) tmp[i]=0;
+ for (i=nvoice+1;i<NUM_VOICES;i++)
+ if ((NoteVoicePar[i].FMVoice==nvoice)&&(tmp[i]==0)){
+ NoteVoicePar[nvoice].VoiceOut=new REALTYPE[SOUND_BUFFER_SIZE];
+ tmp[i]=1;
+ };
+ if (NoteVoicePar[nvoice].VoiceOut!=NULL) for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0;
+ };
+};
+
+
+
+/*
+ * Computes the frequency of an oscillator
+ */
+void ADnote::setfreq(int nvoice,REALTYPE freq){
+ REALTYPE speed;
+ freq=fabs(freq);
+ speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE;
+ if (speed>OSCIL_SIZE) speed=OSCIL_SIZE;
+
+ F2I(speed,oscfreqhi[nvoice]);
+ oscfreqlo[nvoice]=speed-floor(speed);
+};
+
+/*
+ * Computes the frequency of an modullator oscillator
+ */
+void ADnote::setfreqFM(int nvoice,REALTYPE freq){
+ REALTYPE speed;
+ freq=fabs(freq);
+ speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE;
+ if (speed>OSCIL_SIZE) speed=OSCIL_SIZE;
+
+ F2I(speed,oscfreqhiFM[nvoice]);
+ oscfreqloFM[nvoice]=speed-floor(speed);
+};
+
+/*
+ * Get Voice base frequency
+ */
+REALTYPE ADnote::getvoicebasefreq(int nvoice){
+ REALTYPE detune=NoteVoicePar[nvoice].Detune/100.0+
+ NoteVoicePar[nvoice].FineDetune/100.0*ctl->bandwidth.relbw*bandwidthDetuneMultiplier+
+ NoteGlobalPar.Detune/100.0;
+
+ if (NoteVoicePar[nvoice].fixedfreq==0) return(this->basefreq*pow(2,detune/12.0));
+ else {//the fixed freq is enabled
+ REALTYPE fixedfreq=440.0;
+ int fixedfreqET=NoteVoicePar[nvoice].fixedfreqET;
+ 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) fixedfreq*=pow(2.0,tmp);
+ else fixedfreq*=pow(3.0,tmp);
+ };
+ return(fixedfreq*pow(2.0,detune/12.0));
+ };
+};
+
+/*
+ * Get Voice's Modullator base frequency
+ */
+REALTYPE ADnote::getFMvoicebasefreq(int nvoice){
+ REALTYPE detune=NoteVoicePar[nvoice].FMDetune/100.0;
+ return(getvoicebasefreq(nvoice)*pow(2,detune/12.0));
+};
+
+/*
+ * Computes all the parameters for each tick
+ */
+void ADnote::computecurrentparameters(){
+ int nvoice;
+ REALTYPE voicefreq,voicepitch,filterpitch,filterfreq,FMfreq,FMrelativepitch,globalpitch,globalfilterpitch;
+ globalpitch=0.01*(NoteGlobalPar.FreqEnvelope->envout()+
+ NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod);
+ globaloldamplitude=globalnewamplitude;
+ globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout();
+
+ globalfilterpitch=NoteGlobalPar.FilterEnvelope->envout()+NoteGlobalPar.FilterLfo->lfoout()
+ +NoteGlobalPar.FilterCenterPitch;
+
+ REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq
+ +NoteGlobalPar.FilterFreqTracking;
+
+ tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq);
+
+ REALTYPE globalfilterq=NoteGlobalPar.FilterQ*ctl->filterq.relq;
+ NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq,globalfilterq);
+ if (stereo!=0) NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq,globalfilterq);
+
+ //compute the portamento, if it is used by this note
+ REALTYPE portamentofreqrap=1.0;
+ if (portamento!=0){//this voice use portamento
+ portamentofreqrap=ctl->portamento.freqrap;
+ if (ctl->portamento.used==0){//the portamento has finished
+ portamento=0;//this note is no longer "portamented"
+ };
+ };
+
+ //compute parameters for all voices
+ for (nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ if (NoteVoicePar[nvoice].Enabled!=ON) continue;
+ NoteVoicePar[nvoice].DelayTicks-=1;
+ if (NoteVoicePar[nvoice].DelayTicks>0) continue;
+
+ /*******************/
+ /* Voice Amplitude */
+ /*******************/
+ oldamplitude[nvoice]=newamplitude[nvoice];
+ newamplitude[nvoice]=1.0;
+
+ if (NoteVoicePar[nvoice].AmpEnvelope!=NULL)
+ newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB();
+
+ if (NoteVoicePar[nvoice].AmpLfo!=NULL)
+ newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout();
+
+ /****************/
+ /* Voice Filter */
+ /****************/
+ if (NoteVoicePar[nvoice].VoiceFilter!=NULL){
+ filterpitch=NoteVoicePar[nvoice].FilterCenterPitch;
+
+ if (NoteVoicePar[nvoice].FilterEnvelope!=NULL)
+ filterpitch+=NoteVoicePar[nvoice].FilterEnvelope->envout();
+
+ if (NoteVoicePar[nvoice].FilterLfo!=NULL)
+ filterpitch+=NoteVoicePar[nvoice].FilterLfo->lfoout();
+
+ filterfreq=filterpitch+NoteVoicePar[nvoice].FilterFreqTracking;
+ filterfreq=NoteVoicePar[nvoice].VoiceFilter->getrealfreq(filterfreq);
+
+ NoteVoicePar[nvoice].VoiceFilter->setfreq(filterfreq);
+ };
+
+ if (NoteVoicePar[nvoice].noisetype==0){//compute only if the voice isn't noise
+
+ /*******************/
+ /* Voice Frequency */
+ /*******************/
+ voicepitch=0.0;
+ if (NoteVoicePar[nvoice].FreqLfo!=NULL)
+ voicepitch+=NoteVoicePar[nvoice].FreqLfo->lfoout()/100.0
+ *ctl->bandwidth.relbw;
+
+ if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) voicepitch+=NoteVoicePar[nvoice].FreqEnvelope->envout()/100.0;
+ voicefreq=getvoicebasefreq(nvoice)*pow(2,(voicepitch+globalpitch)/12.0);//Hz frequency
+ voicefreq*=ctl->pitchwheel.relfreq;//change the frequency by the controller
+ setfreq(nvoice,voicefreq*portamentofreqrap);
+
+ /***************/
+ /* Modulator */
+ /***************/
+ if (NoteVoicePar[nvoice].FMEnabled!=NONE){
+ FMrelativepitch=NoteVoicePar[nvoice].FMDetune/100.0;
+ if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) FMrelativepitch+=NoteVoicePar[nvoice].FMFreqEnvelope->envout()/100;
+ FMfreq=pow(2.0,FMrelativepitch/12.0)*voicefreq*portamentofreqrap;
+ setfreqFM(nvoice,FMfreq);
+
+ FMoldamplitude[nvoice]=FMnewamplitude[nvoice];
+ FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp;
+ if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL)
+ FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB();
+ };
+ };
+
+ };
+ time+=(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE;
+};
+
+
+/*
+ * Fadein in a way that removes clicks but keep sound "punchy"
+ */
+inline void ADnote::fadein(REALTYPE *smps){
+ int zerocrossings=0;
+ for (int i=1;i<SOUND_BUFFER_SIZE;i++)
+ if ((smps[i-1]<0.0) && (smps[i]>0.0)) zerocrossings++;//this is only the possitive crossings
+
+ REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0;
+ if (tmp<8.0) tmp=8.0;
+
+ int n;
+ F2I(tmp,n);//how many samples is the fade-in
+ if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE;
+ for (int i=0;i<n;i++) {//fade-in
+ REALTYPE tmp=0.5-cos((REALTYPE)i/(REALTYPE) n*PI)*0.5;
+ smps[i]*=tmp;
+ };
+};
+
+/*
+ * Computes the Oscillator (Without Modulation) - LinearInterpolation
+ */
+inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice){
+ int i,poshi;
+ REALTYPE poslo;
+
+ poshi=oscposhi[nvoice];
+ poslo=oscposlo[nvoice];
+ REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ tmpwave[i]=smps[poshi]*(1.0-poslo)+smps[poshi+1]*poslo;
+ poslo+=oscfreqlo[nvoice];
+ if (poslo>=1.0) {
+ poslo-=1.0;
+ poshi++;
+ };
+ poshi+=oscfreqhi[nvoice];
+ poshi&=OSCIL_SIZE-1;
+ };
+ oscposhi[nvoice]=poshi;
+ oscposlo[nvoice]=poslo;
+};
+
+
+
+/*
+ * Computes the Oscillator (Without Modulation) - CubicInterpolation
+ *
+ The differences from the Linear are to little to deserve to be used. This is because I am using a large OSCIL_SIZE (>512)
+inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){
+ int i,poshi;
+ REALTYPE poslo;
+
+ poshi=oscposhi[nvoice];
+ poslo=oscposlo[nvoice];
+ REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp;
+ REALTYPE xm1,x0,x1,x2,a,b,c;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ xm1=smps[poshi];
+ x0=smps[poshi+1];
+ x1=smps[poshi+2];
+ x2=smps[poshi+3];
+ a=(3.0 * (x0-x1) - xm1 + x2) / 2.0;
+ b = 2.0*x1 + xm1 - (5.0*x0 + x2) / 2.0;
+ c = (x1 - xm1) / 2.0;
+ tmpwave[i]=(((a * poslo) + b) * poslo + c) * poslo + x0;
+ printf("a\n");
+ //tmpwave[i]=smps[poshi]*(1.0-poslo)+smps[poshi+1]*poslo;
+ poslo+=oscfreqlo[nvoice];
+ if (poslo>=1.0) {
+ poslo-=1.0;
+ poshi++;
+ };
+ poshi+=oscfreqhi[nvoice];
+ poshi&=OSCIL_SIZE-1;
+ };
+ oscposhi[nvoice]=poshi;
+ oscposlo[nvoice]=poslo;
+};
+*/
+/*
+ * Computes the Oscillator (Morphing)
+ */
+inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice){
+ int i;
+ REALTYPE amp;
+ ComputeVoiceOscillator_LinearInterpolation(nvoice);
+ if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0;
+ if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0;
+
+ if (NoteVoicePar[nvoice].FMVoice>=0){
+ //if I use VoiceOut[] as modullator
+ int FMVoice=NoteVoicePar[nvoice].FMVoice;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ tmpwave[i]=tmpwave[i]*(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i];
+ };
+ } else {
+ int poshiFM=oscposhiFM[nvoice];
+ REALTYPE posloFM=oscposloFM[nvoice];
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ tmpwave[i]=tmpwave[i]*(1.0-amp)+amp
+ *(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1-posloFM)
+ +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM);
+ posloFM+=oscfreqloFM[nvoice];
+ if (posloFM>=1.0) {
+ posloFM-=1.0;
+ poshiFM++;
+ };
+ poshiFM+=oscfreqhiFM[nvoice];
+ poshiFM&=OSCIL_SIZE-1;
+ };
+ oscposhiFM[nvoice]=poshiFM;
+ oscposloFM[nvoice]=posloFM;
+ };
+};
+
+/*
+ * Computes the Oscillator (Ring Modulation)
+ */
+inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice){
+ int i;
+ REALTYPE amp;
+ ComputeVoiceOscillator_LinearInterpolation(nvoice);
+ if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0;
+ if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0;
+ if (NoteVoicePar[nvoice].FMVoice>=0){
+ // if I use VoiceOut[] as modullator
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ int FMVoice=NoteVoicePar[nvoice].FMVoice;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++)
+ tmpwave[i]*=(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i];
+ };
+ } else {
+ int poshiFM=oscposhiFM[nvoice];
+ REALTYPE posloFM=oscposloFM[nvoice];
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ tmpwave[i]*=( NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM)
+ +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM)*amp
+ +(1.0-amp);
+ posloFM+=oscfreqloFM[nvoice];
+ if (posloFM>=1.0) {
+ posloFM-=1.0;
+ poshiFM++;
+ };
+ poshiFM+=oscfreqhiFM[nvoice];
+ poshiFM&=OSCIL_SIZE-1;
+ };
+ oscposhiFM[nvoice]=poshiFM;
+ oscposloFM[nvoice]=posloFM;
+ };
+};
+
+
+
+/*
+ * Computes the Oscillator (Phase Modulation or Frequency Modulation)
+ */
+inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode){
+ int carposhi;
+ int i,FMmodfreqhi;
+ REALTYPE FMmodfreqlo,carposlo;
+
+ if (NoteVoicePar[nvoice].FMVoice>=0){
+ //if I use VoiceOut[] as modulator
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]=NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut[i];
+ } else {
+ //Compute the modulator and store it in tmpwave[]
+ int poshiFM=oscposhiFM[nvoice];
+ REALTYPE posloFM=oscposloFM[nvoice];
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ tmpwave[i]=(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM)
+ +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM);
+ posloFM+=oscfreqloFM[nvoice];
+ if (posloFM>=1.0) {
+ posloFM=fmod(posloFM,1.0);
+ poshiFM++;
+ };
+ poshiFM+=oscfreqhiFM[nvoice];
+ poshiFM&=OSCIL_SIZE-1;
+ };
+ oscposhiFM[nvoice]=poshiFM;
+ oscposloFM[nvoice]=posloFM;
+ };
+ // Amplitude interpolation
+ if (ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice],FMnewamplitude[nvoice])){
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ tmpwave[i]*=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice]
+ ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE);
+ };
+ } else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=FMnewamplitude[nvoice];
+
+
+ //normalize makes all sample-rates, oscil_sizes toproduce same sound
+ if (FMmode!=0){//Frequency modulation
+ REALTYPE normalize=OSCIL_SIZE/262144.0*44100.0/(REALTYPE)SAMPLE_RATE;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ FMoldsmp[nvoice]=fmod(FMoldsmp[nvoice]+tmpwave[i]*normalize,OSCIL_SIZE);
+ tmpwave[i]=FMoldsmp[nvoice];
+ };
+ } else {//Phase modulation
+ REALTYPE normalize=OSCIL_SIZE/262144.0;
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=normalize;
+ };
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ F2I(tmpwave[i],FMmodfreqhi);
+ FMmodfreqlo=fmod(tmpwave[i]+0.0000000001,1.0);
+ if (FMmodfreqhi<0) FMmodfreqlo++;
+
+ //carrier
+ carposhi=oscposhi[nvoice]+FMmodfreqhi;
+ carposlo=oscposlo[nvoice]+FMmodfreqlo;
+
+ if (carposlo>=1.0) {
+ carposhi++;
+ carposlo=fmod(carposlo,1.0);
+ };
+ carposhi&=(OSCIL_SIZE-1);
+
+ tmpwave[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo)
+ +NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo;
+
+ oscposlo[nvoice]+=oscfreqlo[nvoice];
+ if (oscposlo[nvoice]>=1.0) {
+ oscposlo[nvoice]=fmod(oscposlo[nvoice],1.0);
+ oscposhi[nvoice]++;
+ };
+
+ oscposhi[nvoice]+=oscfreqhi[nvoice];
+ oscposhi[nvoice]&=OSCIL_SIZE-1;
+ };
+};
+
+
+/*Calculeaza Oscilatorul cu PITCH MODULATION*/
+inline void ADnote::ComputeVoiceOscillatorPitchModulation(int nvoice){
+//TODO
+};
+
+/*
+ * Computes the Noise
+ */
+inline void ADnote::ComputeVoiceNoise(int nvoice){
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]=RND*2.0-1.0;
+};
+
+
+
+/*
+ * Compute the ADnote samples
+ * Returns 0 if the note is finished
+ */
+int ADnote::noteout(REALTYPE *outl,REALTYPE *outr){
+ int i,nvoice;
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ outl[i]=denormalkillbuf[i];
+ outr[i]=denormalkillbuf[i];
+ };
+
+ if (NoteEnabled==OFF) return(0);
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ bypassl[i]=0.0;
+ bypassr[i]=0.0;
+ };
+
+ computecurrentparameters();
+
+ for (nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ if ((NoteVoicePar[nvoice].Enabled!=ON) || (NoteVoicePar[nvoice].DelayTicks>0)) continue;
+ if (NoteVoicePar[nvoice].noisetype==0){//voice mode=sound
+ switch (NoteVoicePar[nvoice].FMEnabled){
+ case MORPH:ComputeVoiceOscillatorMorph(nvoice);break;
+ case RING_MOD:ComputeVoiceOscillatorRingModulation(nvoice);break;
+ case PHASE_MOD:ComputeVoiceOscillatorFrequencyModulation(nvoice,0);break;
+ case FREQ_MOD:ComputeVoiceOscillatorFrequencyModulation(nvoice,1);break;
+ //case PITCH_MOD:ComputeVoiceOscillatorPitchModulation(nvoice);break;
+ default:ComputeVoiceOscillator_LinearInterpolation(nvoice);
+ //if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice);
+
+ };
+ } else ComputeVoiceNoise(nvoice);
+ // Voice Processing
+
+ // Amplitude
+ if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude[nvoice],newamplitude[nvoice])){
+ int rest=SOUND_BUFFER_SIZE;
+ //test if the amplitude if raising and the difference is high
+ if ((newamplitude[nvoice]>oldamplitude[nvoice])&&((newamplitude[nvoice]-oldamplitude[nvoice])>0.25)){
+ rest=10;
+ if (rest>SOUND_BUFFER_SIZE) rest=SOUND_BUFFER_SIZE;
+ for (int i=0;i<SOUND_BUFFER_SIZE-rest;i++) tmpwave[i]*=oldamplitude[nvoice];
+ };
+ // Amplitude interpolation
+ for (i=0;i<rest;i++){
+ tmpwave[i+(SOUND_BUFFER_SIZE-rest)]*=INTERPOLATE_AMPLITUDE(oldamplitude[nvoice]
+ ,newamplitude[nvoice],i,rest);
+ };
+ } else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=newamplitude[nvoice];
+
+ // Fade in
+ if (firsttick[nvoice]!=0){
+ fadein(&tmpwave[0]);
+ firsttick[nvoice]=0;
+ };
+
+
+ // Filter
+ if (NoteVoicePar[nvoice].VoiceFilter!=NULL) NoteVoicePar[nvoice].VoiceFilter->filterout(&tmpwave[0]);
+
+ //check if the amplitude envelope is finished, if yes, the voice will be fadeout
+ if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) {
+ if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0)
+ for (i=0;i<SOUND_BUFFER_SIZE;i++)
+ tmpwave[i]*=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
+ //the voice is killed later
+ };
+
+
+ // Put the ADnote samples in VoiceOut (without appling Global volume, because I wish to use this voice as a modullator)
+ if (NoteVoicePar[nvoice].VoiceOut!=NULL)
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=tmpwave[i];
+
+
+ // Add the voice that do not bypass the filter to out
+ if (NoteVoicePar[nvoice].filterbypass==0){//no bypass
+ if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono
+ else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo
+ outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0;
+ outr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0;
+ };
+ } else {//bypass the filter
+ if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono
+ else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo
+ bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0;
+ bypassr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0;
+ };
+ };
+ // chech if there is necesary to proces the voice longer (if the Amplitude envelope isn't finished)
+ if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) {
+ if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0) KillVoice(nvoice);
+ };
+ };
+
+
+ //Processing Global parameters
+ NoteGlobalPar.GlobalFilterL->filterout(&outl[0]);
+
+ if (stereo==0) {
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {//set the right channel=left channel
+ outr[i]=outl[i];
+ bypassr[i]=bypassl[i];
+ }
+ } else NoteGlobalPar.GlobalFilterR->filterout(&outr[0]);
+
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ outl[i]+=bypassl[i];
+ outr[i]+=bypassr[i];
+ };
+
+ if (ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude,globalnewamplitude)){
+ // Amplitude Interpolation
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(globaloldamplitude
+ ,globalnewamplitude,i,SOUND_BUFFER_SIZE);
+ outl[i]*=tmpvol*NoteGlobalPar.Panning;
+ outr[i]*=tmpvol*(1.0-NoteGlobalPar.Panning);
+ };
+ } else {
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ outl[i]*=globalnewamplitude*NoteGlobalPar.Panning;
+ outr[i]*=globalnewamplitude*(1.0-NoteGlobalPar.Panning);
+ };
+ };
+
+ //Apply the punch
+ if (NoteGlobalPar.Punch.Enabled!=0){
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ REALTYPE punchamp=NoteGlobalPar.Punch.initialvalue*NoteGlobalPar.Punch.t+1.0;
+ outl[i]*=punchamp;
+ outr[i]*=punchamp;
+ NoteGlobalPar.Punch.t-=NoteGlobalPar.Punch.dt;
+ if (NoteGlobalPar.Punch.t<0.0) {
+ NoteGlobalPar.Punch.Enabled=0;
+ break;
+ };
+ };
+ };
+
+ // Check if the global amplitude is finished.
+ // If it does, disable the note
+ if (NoteGlobalPar.AmpEnvelope->finished()!=0) {
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out
+ REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
+ outl[i]*=tmp;
+ outr[i]*=tmp;
+ };
+ KillNote();
+ };
+ return(1);
+};
+
+
+/*
+ * Relase the key (NoteOff)
+ */
+void ADnote::relasekey(){
+int nvoice;
+ for (nvoice=0;nvoice<NUM_VOICES;nvoice++){
+ if (NoteVoicePar[nvoice].Enabled==0) continue;
+ if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) NoteVoicePar[nvoice].AmpEnvelope->relasekey();
+ if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) NoteVoicePar[nvoice].FreqEnvelope->relasekey();
+ if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) NoteVoicePar[nvoice].FilterEnvelope->relasekey();
+ if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) NoteVoicePar[nvoice].FMFreqEnvelope->relasekey();
+ if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) NoteVoicePar[nvoice].FMAmpEnvelope->relasekey();
+ };
+ NoteGlobalPar.FreqEnvelope->relasekey();
+ NoteGlobalPar.FilterEnvelope->relasekey();
+ NoteGlobalPar.AmpEnvelope->relasekey();
+
+};
+
+/*
+ * Check if the note is finished
+ */
+int ADnote::finished(){
+ if (NoteEnabled==ON) return(0);
+ else return(1);
+};
+
+
+
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.h b/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.h
new file mode 100644
index 00000000..28c18975
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/ADnote.h
@@ -0,0 +1,258 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ ADnote.h - The "additive" 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
+
+*/
+
+#ifndef AD_NOTE_H
+#define AD_NOTE_H
+
+#include "../globals.h"
+#include "Envelope.h"
+#include "LFO.h"
+#include "../DSP/Filter.h"
+#include "../Params/ADnoteParameters.h"
+#include "../Params/Controller.h"
+
+//Globals
+
+//FM amplitude tune
+#define FM_AMP_MULTIPLIER 14.71280603
+
+#define OSCIL_SMP_EXTRA_SAMPLES 5
+
+class ADnote{ //ADDitive note
+ public:
+ ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_);
+ ~ADnote();
+ int noteout(REALTYPE *outl,REALTYPE *outr);
+ void relasekey();
+ int finished();
+
+
+ /*ready - this is 0 if it is not ready (the parameters has to be computed)
+ or other value if the parameters has been computed and if it is ready to output*/
+ char ready;
+
+ private:
+
+ void setfreq(int nvoice,REALTYPE freq);
+ void setfreqFM(int nvoice,REALTYPE freq);
+ void computecurrentparameters();
+ void initparameters();
+ void KillVoice(int nvoice);
+ void KillNote();
+ inline REALTYPE getvoicebasefreq(int nvoice);
+ inline REALTYPE getFMvoicebasefreq(int nvoice);
+ inline void ComputeVoiceOscillator_LinearInterpolation(int nvoice);
+ inline void ComputeVoiceOscillator_CubicInterpolation(int nvoice);
+ inline void ComputeVoiceOscillatorMorph(int nvoice);
+ inline void ComputeVoiceOscillatorRingModulation(int nvoice);
+ inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode);//FMmode=0 for phase modulation, 1 for Frequency modulation
+// inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice);
+ inline void ComputeVoiceOscillatorPitchModulation(int nvoice);
+
+ inline void ComputeVoiceNoise(int nvoice);
+
+ inline void fadein(REALTYPE *smps);
+
+
+ //GLOBALS
+ ADnoteParameters *partparams;
+ unsigned char stereo;//if the note is stereo (allows note Panning)
+ int midinote;
+ REALTYPE velocity,basefreq;
+
+ ONOFFTYPE NoteEnabled;
+ Controller *ctl;
+
+ /*****************************************************************/
+ /* GLOBAL PARAMETERS */
+ /*****************************************************************/
+
+ struct ADnoteGlobal{
+ /******************************************
+ * FREQUENCY GLOBAL PARAMETERS *
+ ******************************************/
+ REALTYPE Detune;//cents
+
+ Envelope *FreqEnvelope;
+ LFO *FreqLfo;
+
+ /********************************************
+ * AMPLITUDE GLOBAL PARAMETERS *
+ ********************************************/
+ REALTYPE Volume;// [ 0 .. 1 ]
+
+ REALTYPE Panning;// [ 0 .. 1 ]
+
+ Envelope *AmpEnvelope;
+ LFO *AmpLfo;
+
+ struct {
+ int Enabled;
+ REALTYPE initialvalue,dt,t;
+ } Punch;
+
+ /******************************************
+ * FILTER GLOBAL PARAMETERS *
+ ******************************************/
+ Filter *GlobalFilterL,*GlobalFilterR;
+
+ REALTYPE FilterCenterPitch;//octaves
+ REALTYPE FilterQ;
+ REALTYPE FilterFreqTracking;
+
+ Envelope *FilterEnvelope;
+
+ LFO *FilterLfo;
+ } NoteGlobalPar;
+
+
+
+ /***********************************************************/
+ /* VOICE PARAMETERS */
+ /***********************************************************/
+ struct ADnoteVoice{
+ /* If the voice is enabled */
+ ONOFFTYPE Enabled;
+
+ /* Voice Type (sound/noise)*/
+ int noisetype;
+
+ /* Filter Bypass */
+ int filterbypass;
+
+ /* Delay (ticks) */
+ int DelayTicks;
+
+ /* Waveform of the Voice */
+ REALTYPE *OscilSmp;
+
+ /************************************
+ * FREQUENCY PARAMETERS *
+ ************************************/
+ int fixedfreq;//if the frequency is fixed to 440 Hz
+ int fixedfreqET;//if the "fixed" frequency varies according to the note (ET)
+
+ // cents = basefreq*VoiceDetune
+ REALTYPE Detune,FineDetune;
+
+ Envelope *FreqEnvelope;
+ LFO *FreqLfo;
+
+
+ /***************************
+ * AMPLITUDE PARAMETERS *
+ ***************************/
+
+ /* Panning 0.0=left, 0.5 - center, 1.0 = right */
+ REALTYPE Panning;
+ REALTYPE Volume;// [-1.0 .. 1.0]
+
+ Envelope *AmpEnvelope;
+ LFO *AmpLfo;
+
+ /*************************
+ * FILTER PARAMETERS *
+ *************************/
+
+ Filter *VoiceFilter;
+
+ REALTYPE FilterCenterPitch;/* Filter center Pitch*/
+ REALTYPE FilterFreqTracking;
+
+ Envelope *FilterEnvelope;
+ LFO *FilterLfo;
+
+
+ /****************************
+ * MODULLATOR PARAMETERS *
+ ****************************/
+
+ FMTYPE FMEnabled;
+
+ int FMVoice;
+
+ // Voice Output used by other voices if use this as modullator
+ REALTYPE *VoiceOut;
+
+ /* Wave of the Voice */
+ REALTYPE *FMSmp;
+
+ REALTYPE FMVolume;
+ REALTYPE FMDetune; //in cents
+
+ Envelope *FMFreqEnvelope;
+ Envelope *FMAmpEnvelope;
+ } NoteVoicePar[NUM_VOICES];
+
+
+ /********************************************************/
+ /* INTERNAL VALUES OF THE NOTE AND OF THE VOICES */
+ /********************************************************/
+
+ //time from the start of the note
+ REALTYPE time;
+
+ //fractional part (skip)
+ REALTYPE oscposlo[NUM_VOICES],oscfreqlo[NUM_VOICES];
+
+ //integer part (skip)
+ int oscposhi[NUM_VOICES],oscfreqhi[NUM_VOICES];
+
+ //fractional part (skip) of the Modullator
+ REALTYPE oscposloFM[NUM_VOICES],oscfreqloFM[NUM_VOICES];
+
+ //integer part (skip) of the Modullator
+ unsigned short int oscposhiFM[NUM_VOICES],oscfreqhiFM[NUM_VOICES];
+
+ //used to compute and interpolate the amplitudes of voices and modullators
+ REALTYPE oldamplitude[NUM_VOICES],
+ newamplitude[NUM_VOICES],
+ FMoldamplitude[NUM_VOICES],
+ FMnewamplitude[NUM_VOICES];
+
+ //used by Frequency Modulation (for integration)
+ REALTYPE FMoldsmp[NUM_VOICES];
+
+ //temporary buffer
+ REALTYPE *tmpwave;
+
+ //Filter bypass samples
+ REALTYPE *bypassl,*bypassr;
+
+ //interpolate the amplitudes
+ REALTYPE globaloldamplitude,globalnewamplitude;
+
+ //1 - if it is the fitst tick (used to fade in the sound)
+ char firsttick[NUM_VOICES];
+
+ //1 if the note has portamento
+ int portamento;
+
+ //how the fine detunes are made bigger or smaller
+ REALTYPE bandwidthDetuneMultiplier;
+};
+
+#endif
+
+
+
+
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/Envelope.C b/muse_qt4_evolution/synti/zynaddsubfx/Synth/Envelope.C
new file mode 100644
index 00000000..a0194022
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/Envelope.C
@@ -0,0 +1,165 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Envelope.C - Envelope implementation
+ 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 <stdio.h>
+#include "Envelope.h"
+
+Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq){
+ int i;
+ envpoints=envpars->Penvpoints;
+ if (envpoints>MAX_ENVELOPE_POINTS) envpoints=MAX_ENVELOPE_POINTS;
+ envsustain=(envpars->Penvsustain==0)?-1:envpars->Penvsustain;
+ forcedrelase=envpars->Pforcedrelease;
+ envstretch=pow(440.0/basefreq,envpars->Penvstretch/64.0);
+ linearenvelope=envpars->Plinearenvelope;
+
+ if (envpars->Pfreemode==0) envpars->converttofree();
+
+ REALTYPE bufferdt=SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE;
+
+ int mode=envpars->Envmode;
+
+ //for amplitude envelopes
+ if ((mode==1)&&(linearenvelope==0)) mode=2;//change to log envelope
+ if ((mode==2)&&(linearenvelope!=0)) mode=1;//change to linear
+
+ for (i=0;i<MAX_ENVELOPE_POINTS;i++) {
+ REALTYPE tmp=envpars->getdt(i)/1000.0*envstretch;
+ if (tmp>bufferdt) envdt[i]=bufferdt/tmp;
+ else envdt[i]=2.0;//any value larger than 1
+
+ switch (mode){
+ case 2:envval[i]=(1.0-envpars->Penvval[i]/127.0)*MIN_ENVELOPE_DB;
+ break;
+ case 3:envval[i]=(pow(2,6.0*fabs(envpars->Penvval[i]-64.0)/64.0)-1.0)*100.0;
+ if (envpars->Penvval[i]<64) envval[i]=-envval[i];
+ break;
+ case 4:envval[i]=(envpars->Penvval[i]-64.0)/64.0*6.0;//6 octaves (filtru)
+ break;
+ case 5:envval[i]=(envpars->Penvval[i]-64.0)/64.0*10;
+ break;
+ default:envval[i]=envpars->Penvval[i]/127.0;
+ };
+
+ };
+
+ envdt[0]=1.0;
+
+ currentpoint=1;//the envelope starts from 1
+ keyreleased=0;
+ t=0.0;
+ envfinish=0;
+ inct=envdt[1];
+ envoutval=0.0;
+};
+
+Envelope::~Envelope(){
+};
+
+
+/*
+ * Relase the key (note envelope)
+ */
+void Envelope::relasekey(){
+ if (keyreleased==1) return;
+ keyreleased=1;
+ if (forcedrelase!=0) t=0.0;
+};
+
+/*
+ * Envelope Output
+ */
+REALTYPE Envelope::envout(){
+ REALTYPE out;
+
+ if (envfinish!=0) {//if the envelope is finished
+ envoutval=envval[envpoints-1];
+ return(envoutval);
+ };
+ if ((currentpoint==envsustain+1)&&(keyreleased==0)) {//if it is sustaining now
+ envoutval=envval[envsustain];
+ return(envoutval);
+ };
+
+ if ((keyreleased!=0) && (forcedrelase!=0)){//do the forced release
+
+ int tmp=(envsustain<0) ? (envpoints-1):(envsustain+1);//if there is no sustain point, use the last point for release
+
+ if (envdt[tmp]<0.00000001) out=envval[tmp];
+ else out=envoutval+(envval[tmp]-envoutval)*t;
+ t+=envdt[tmp]*envstretch;
+
+ if (t>=1.0) {
+ currentpoint=envsustain+2;
+ forcedrelase=0;
+ t=0.0;
+ inct=envdt[currentpoint];
+ if ((currentpoint>=envpoints)||(envsustain<0)) envfinish=1;
+ };
+ return(out);
+ };
+ if (inct>=1.0) out=envval[currentpoint];
+ else out=envval[currentpoint-1]+(envval[currentpoint]-envval[currentpoint-1])*t;
+
+ t+=inct;
+ if (t>=1.0){
+ if (currentpoint>=envpoints-1) envfinish=1;
+ else currentpoint++;
+ t=0.0;
+ inct=envdt[currentpoint];
+ };
+
+ envoutval=out;
+ return (out);
+};
+
+/*
+ * Envelope Output (dB)
+ */
+REALTYPE Envelope::envout_dB(){
+ REALTYPE out;
+ if (linearenvelope!=0) return (envout());
+
+ if ((currentpoint==1)&&((keyreleased==0)||(forcedrelase==0))) {//first point is always lineary interpolated
+ REALTYPE v1=dB2rap(envval[0]);
+ REALTYPE v2=dB2rap(envval[1]);
+ out=v1+(v2-v1)*t;
+
+ t+=inct;
+ if (t>=1.0) {
+ t=0.0;
+ inct=envdt[2];
+ currentpoint++;
+ out=v2;
+ };
+
+ if (out>0.001) envoutval=rap2dB(out);
+ else envoutval=-40.0;
+ } else out=dB2rap(envout());
+
+ return(out);
+};
+
+int Envelope::finished(){
+ return(envfinish);
+};
+
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/Envelope.h b/muse_qt4_evolution/synti/zynaddsubfx/Synth/Envelope.h
new file mode 100644
index 00000000..d78eb16d
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/Envelope.h
@@ -0,0 +1,58 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Envelope.h - Envelope implementation
+ 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 ENVELOPE_H
+#define ENVELOPE_H
+
+#include <math.h>
+#include "../globals.h"
+#include "../Params/EnvelopeParams.h"
+
+class Envelope{
+public:
+ Envelope(EnvelopeParams *envpars,REALTYPE basefreq);
+ ~Envelope();
+ void relasekey();
+ REALTYPE envout();
+ REALTYPE envout_dB();
+ int finished();//returns 1 if the envelope is finished
+private:
+ int envpoints;
+ int envsustain;//"-1" means disabled
+ REALTYPE envdt[MAX_ENVELOPE_POINTS];//millisecons
+ REALTYPE envval[MAX_ENVELOPE_POINTS];// [0.0 .. 1.0]
+ REALTYPE envstretch;
+ int linearenvelope;
+
+ int currentpoint; //current envelope point (starts from 1)
+ int forcedrelase;
+ char keyreleased; //if the key was released
+ char envfinish;
+ REALTYPE t; // the time from the last point
+ REALTYPE inct;// the time increment
+ REALTYPE envoutval;//used to do the forced release
+};
+
+
+#endif
+
+
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/LFO.C b/muse_qt4_evolution/synti/zynaddsubfx/Synth/LFO.C
new file mode 100644
index 00000000..4ae548c1
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/LFO.C
@@ -0,0 +1,145 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ LFO.C - LFO implementation
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "LFO.h"
+
+
+LFO::LFO(LFOParams *lfopars,REALTYPE basefreq){
+ if (lfopars->Pstretch==0) lfopars->Pstretch=1;
+ REALTYPE lfostretch=pow(basefreq/440.0,(lfopars->Pstretch-64.0)/63.0);//max 2x/octave
+
+ REALTYPE lfofreq=(pow(2,lfopars->Pfreq*10.0)-1.0)/12.0*lfostretch;
+ incx=fabs(lfofreq)*(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE;
+
+ if (lfopars->Pcontinous==0){
+ if (lfopars->Pstartphase==0) x=RND;
+ else x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0,1.0);
+ } else {
+ REALTYPE tmp=fmod(lfopars->time*incx,1.0);
+ x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0+tmp,1.0);
+ };
+
+ //Limit the Frequency(or else...)
+ if (incx>0.49999999) incx=0.499999999;
+
+
+ lfornd=lfopars->Prandomness/127.0;
+ if (lfornd<0.0) lfornd=0.0; else if (lfornd>1.0) lfornd=1.0;
+
+// lfofreqrnd=pow(lfopars->Pfreqrand/127.0,2.0)*2.0*4.0;
+ lfofreqrnd=pow(lfopars->Pfreqrand/127.0,2.0)*4.0;
+
+ switch (lfopars->fel){
+ case 1:lfointensity=lfopars->Pintensity/127.0;break;
+ case 2:lfointensity=lfopars->Pintensity/127.0*4.0;break;//in octave
+ default:lfointensity=pow(2,lfopars->Pintensity/127.0*11.0)-1.0;//in centi
+ x-=0.25;//chance the starting phase
+ break;
+ };
+
+ amp1=(1-lfornd)+lfornd*RND;
+ amp2=(1-lfornd)+lfornd*RND;
+ lfotype=lfopars->PLFOtype;
+ lfodelay=lfopars->Pdelay/127.0*4.0;//0..4 sec
+ incrnd=nextincrnd=1.0;
+ freqrndenabled=(lfopars->Pfreqrand!=0);
+ computenextincrnd();
+ computenextincrnd();//twice because I want incrnd & nextincrnd to be random
+};
+
+LFO::~LFO(){
+};
+
+/*
+ * LFO out
+ */
+REALTYPE LFO::lfoout(){
+ REALTYPE out;
+ switch (lfotype){
+ case 1: //LFO_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;
+ break;
+ case 2: //LFO_SQUARE
+ if (x<0.5) out=-1;
+ else out=1;
+ break;
+ case 3: //LFO_RAMPUP
+ out=(x-0.5)*2.0;
+ break;
+ case 4: //LFO_RAMPDOWN
+ out=(0.5-x)*2.0;
+ break;
+ case 5: //LFO_EXP_DOWN 1
+ out=pow(0.05,x)*2.0-1.0;
+ break;
+ case 6: //LFO_EXP_DOWN 2
+ out=pow(0.001,x)*2.0-1.0;
+ break;
+ default:out=cos(x*2.0*PI);//LFO_SINE
+ };
+
+
+ if ((lfotype==0)||(lfotype==1)) out*=lfointensity*(amp1+x*(amp2-amp1));
+ else out*=lfointensity*amp2;
+ if (lfodelay<0.00001) {
+ if (freqrndenabled==0) x+=incx;
+ else {
+ float tmp=(incrnd*(1.0-x)+nextincrnd*x);
+ if (tmp>1.0) tmp=1.0;
+ else if (tmp<0.0) tmp=0.0;
+ x+=incx*tmp;
+ };
+ if (x>=1) {
+ x=fmod(x,1.0);
+ amp1=amp2;
+ amp2=(1-lfornd)+lfornd*RND;
+
+ computenextincrnd();
+ };
+ } else lfodelay-=(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE;
+ return(out);
+};
+
+/*
+ * LFO out (for amplitude)
+ */
+REALTYPE LFO::amplfoout(){
+ REALTYPE out;
+ out=1.0-lfointensity+lfoout();
+ if (out<-1.0) out=-1.0;
+ else if (out>1.0) out=1.0;
+ return(out);
+};
+
+
+void LFO::computenextincrnd(){
+ if (freqrndenabled==0) return;
+ incrnd=nextincrnd;
+ nextincrnd=pow(0.5,lfofreqrnd)+RND*(pow(2.0,lfofreqrnd)-1.0);
+};
+
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/LFO.h b/muse_qt4_evolution/synti/zynaddsubfx/Synth/LFO.h
new file mode 100644
index 00000000..30d04f10
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/LFO.h
@@ -0,0 +1,52 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ LFO.h - LFO implementation
+ 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 LFO_H
+#define LFO_H
+
+#include "../globals.h"
+#include "../Params/LFOParams.h"
+
+
+class LFO{
+ public:
+ LFO(LFOParams *lfopars, REALTYPE basefreq);
+ ~LFO();
+ REALTYPE lfoout();
+ REALTYPE amplfoout();
+ private:
+ REALTYPE x;
+ REALTYPE incx,incrnd,nextincrnd;
+ REALTYPE amp1,amp2;// used for randomness
+ REALTYPE lfointensity;
+ REALTYPE lfornd,lfofreqrnd;
+ REALTYPE lfodelay;
+ char lfotype;
+ int freqrndenabled;
+
+
+ void computenextincrnd();
+
+};
+
+
+#endif
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/OscilGen.C b/muse_qt4_evolution/synti/zynaddsubfx/Synth/OscilGen.C
new file mode 100644
index 00000000..4e6a4dd3
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/OscilGen.C
@@ -0,0 +1,1182 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ OscilGen.C - Waveform generator for ADnote
+ 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 <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "OscilGen.h"
+#include "../Effects/Distorsion.h"
+
+REALTYPE *OscilGen::tmpsmps;//this array stores some termporary data and it has SOUND_BUFFER_SIZE elements
+FFTFREQS OscilGen::outoscilFFTfreqs;
+
+
+OscilGen::OscilGen(FFTwrapper *fft_,Resonance *res_):Presets(){
+ setpresettype("Poscilgen");
+ fft=fft_;
+ res=res_;
+ newFFTFREQS(&oscilFFTfreqs,OSCIL_SIZE/2);
+ newFFTFREQS(&basefuncFFTfreqs,OSCIL_SIZE/2);
+
+ randseed=1;
+ ADvsPAD=false;
+
+ defaults();
+};
+
+OscilGen::~OscilGen(){
+ deleteFFTFREQS(&basefuncFFTfreqs);
+ deleteFFTFREQS(&oscilFFTfreqs);
+};
+
+
+void OscilGen::defaults(){
+
+ oldbasefunc=0;oldbasepar=64;oldhmagtype=0;oldwaveshapingfunction=0;oldwaveshaping=64;
+ oldbasefuncmodulation=0;oldharmonicshift=0;oldbasefuncmodulationpar1=0;oldbasefuncmodulationpar2=0;oldbasefuncmodulationpar3=0;
+ oldmodulation=0;oldmodulationpar1=0;oldmodulationpar2=0;oldmodulationpar3=0;
+
+ for (int i=0;i<MAX_AD_HARMONICS;i++){
+ hmag[i]=0.0;
+ hphase[i]=0.0;
+ Phmag[i]=64;
+ Phphase[i]=64;
+ };
+ Phmag[0]=127;
+ Phmagtype=0;
+ if (ADvsPAD) Prand=127;//max phase randomness (usefull if the oscil will be imported to a ADsynth from a PADsynth
+ else Prand=64;//no randomness
+
+ Pcurrentbasefunc=0;
+ Pbasefuncpar=64;
+
+ Pbasefuncmodulation=0;
+ Pbasefuncmodulationpar1=64;
+ Pbasefuncmodulationpar2=64;
+ Pbasefuncmodulationpar3=32;
+
+ Pmodulation=0;
+ Pmodulationpar1=64;
+ Pmodulationpar2=64;
+ Pmodulationpar3=32;
+
+ Pwaveshapingfunction=0;
+ Pwaveshaping=64;
+ Pfiltertype=0;
+ Pfilterpar1=64;
+ Pfilterpar2=64;
+ Pfilterbeforews=0;
+ Psatype=0;
+ Psapar=64;
+
+ Pamprandpower=64;
+ Pamprandtype=0;
+
+ Pharmonicshift=0;
+ Pharmonicshiftfirst=0;
+
+ Padaptiveharmonics=0;
+ Padaptiveharmonicspower=100;
+ Padaptiveharmonicsbasefreq=128;
+ Padaptiveharmonicspar=50;
+
+ for (int i=0;i<OSCIL_SIZE/2;i++) {
+ oscilFFTfreqs.s[i]=0.0;
+ oscilFFTfreqs.c[i]=0.0;
+ basefuncFFTfreqs.s[i]=0.0;
+ basefuncFFTfreqs.c[i]=0.0;
+ };
+ oscilprepared=0;
+ oldfilterpars=0;oldsapars=0;
+ prepare();
+};
+
+void OscilGen::convert2sine(int magtype){
+ REALTYPE mag[MAX_AD_HARMONICS],phase[MAX_AD_HARMONICS];
+ REALTYPE oscil[OSCIL_SIZE];
+ FFTFREQS freqs;
+ newFFTFREQS(&freqs,OSCIL_SIZE/2);
+
+ get(oscil,-1.0);
+ FFTwrapper *fft=new FFTwrapper(OSCIL_SIZE);
+ fft->smps2freqs(oscil,freqs);
+ delete(fft);
+
+ REALTYPE max=0.0;
+
+ mag[0]=0;
+ phase[0]=0;
+ for (int i=0;i<MAX_AD_HARMONICS;i++){
+ mag[i]=sqrt(pow(freqs.s[i+1],2)+pow(freqs.c[i+1],2.0));
+ phase[i]=atan2(freqs.c[i+1],freqs.s[i+1]);
+ if (max<mag[i]) max=mag[i];
+ };
+ if (max<0.00001) max=1.0;
+
+ defaults();
+
+ for (int i=0;i<MAX_AD_HARMONICS-1;i++){
+ REALTYPE newmag=mag[i]/max;
+ REALTYPE newphase=phase[i];
+
+ Phmag[i]=(int) ((newmag)*64.0)+64;
+
+ Phphase[i]=64-(int) (64.0*newphase/PI);
+ if (Phphase[i]>127) Phphase[i]=127;
+
+ if (Phmag[i]==64) Phphase[i]=64;
+ };
+ deleteFFTFREQS(&freqs);
+ prepare();
+};
+
+/*
+ * Base Functions - START
+ */
+REALTYPE OscilGen::basefunc_pulse(REALTYPE x,REALTYPE a){
+ return((fmod(x,1.0)<a)?-1.0:1.0);
+};
+
+REALTYPE OscilGen::basefunc_saw(REALTYPE x,REALTYPE a){
+ if (a<0.00001) a=0.00001;
+ else if (a>0.99999) a=0.99999;
+ x=fmod(x,1);
+ if (x<a) return(x/a*2.0-1.0);
+ else return((1.0-x)/(1.0-a)*2.0-1.0);
+};
+
+REALTYPE OscilGen::basefunc_triangle(REALTYPE x,REALTYPE a){
+ x=fmod(x+0.25,1);
+ a=1-a;
+ if (a<0.00001) a=0.00001;
+ if (x<0.5) x=x*4-1.0;
+ else x=(1.0-x)*4-1.0;
+ x/=-a;
+ if (x<-1.0) x=-1.0;
+ if (x>1.0) x=1.0;
+ return(x);
+};
+
+REALTYPE OscilGen::basefunc_power(REALTYPE x,REALTYPE a){
+ x=fmod(x,1);
+ if (a<0.00001) a=0.00001;
+ else if (a>0.99999) a=0.99999;
+ return(pow(x,exp((a-0.5)*10.0))*2.0-1.0);
+};
+
+REALTYPE OscilGen::basefunc_gauss(REALTYPE x,REALTYPE a){
+ x=fmod(x,1)*2.0-1.0;
+ if (a<0.00001) a=0.00001;
+ return(exp(-x*x*(exp(a*8)+5.0))*2.0-1.0);
+};
+
+REALTYPE OscilGen::basefunc_diode(REALTYPE x,REALTYPE a){
+ if (a<0.00001) a=0.00001;
+ else if (a>0.99999) a=0.99999;
+ a=a*2.0-1.0;
+ x=cos((x+0.5)*2.0*PI)-a;
+ if (x<0.0) x=0.0;
+ return(x/(1.0-a)*2-1.0);
+};
+
+REALTYPE OscilGen::basefunc_abssine(REALTYPE x,REALTYPE a){
+ x=fmod(x,1);
+ if (a<0.00001) a=0.00001;
+ else if (a>0.99999) a=0.99999;
+ return(sin(pow(x,exp((a-0.5)*5.0))*PI)*2.0-1.0);
+};
+
+REALTYPE OscilGen::basefunc_pulsesine(REALTYPE x,REALTYPE a){
+ if (a<0.00001) a=0.00001;
+ x=(fmod(x,1)-0.5)*exp((a-0.5)*log(128));
+ if (x<-0.5) x=-0.5;
+ else if (x>0.5) x=0.5;
+ x=sin(x*PI*2.0);
+ return(x);
+};
+
+REALTYPE OscilGen::basefunc_stretchsine(REALTYPE x,REALTYPE a){
+ x=fmod(x+0.5,1)*2.0-1.0;
+ a=(a-0.5)*4;if (a>0.0) a*=2;
+ a=pow(3.0,a);
+ REALTYPE b=pow(fabs(x),a);
+ if (x<0) b=-b;
+ return(-sin(b*PI));
+};
+
+REALTYPE OscilGen::basefunc_chirp(REALTYPE x,REALTYPE a){
+ x=fmod(x,1.0)*2.0*PI;
+ a=(a-0.5)*4;if (a<0.0) a*=2.0;
+ a=pow(3.0,a);
+ return(sin(x/2.0)*sin(a*x*x));
+};
+
+REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x,REALTYPE a){
+ x=fmod(x+0.5,1)*2.0-1.0;
+ a=(a-0.5)*9;
+ a=pow(3.0,a);
+ REALTYPE b=pow(fabs(x),a);
+ if (x<0) b=-b;
+ return(-pow(sin(b*PI),2));
+};
+
+REALTYPE OscilGen::basefunc_chebyshev(REALTYPE x,REALTYPE a){
+ a=a*a*a*30.0+1.0;
+ return(cos(acos(x*2.0-1.0)*a));
+};
+
+REALTYPE OscilGen::basefunc_sqr(REALTYPE x,REALTYPE a){
+ a=a*a*a*a*160.0+0.001;
+ return(-atan(sin(x*2.0*PI)*a));
+};
+/*
+ * Base Functions - END
+ */
+
+
+/*
+ * Get the base function
+ */
+void OscilGen::getbasefunction(REALTYPE *smps){
+ int i;
+ REALTYPE par=(Pbasefuncpar+0.5)/128.0;
+ if (Pbasefuncpar==64) par=0.5;
+
+ REALTYPE basefuncmodulationpar1=Pbasefuncmodulationpar1/127.0,
+ basefuncmodulationpar2=Pbasefuncmodulationpar2/127.0,
+ basefuncmodulationpar3=Pbasefuncmodulationpar3/127.0;
+
+ switch(Pbasefuncmodulation){
+ case 1:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0;
+ basefuncmodulationpar3=floor((pow(2,basefuncmodulationpar3*5.0)-1.0));
+ if (basefuncmodulationpar3<0.9999) basefuncmodulationpar3=-1.0;
+ break;
+ case 2:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0;
+ basefuncmodulationpar3=1.0+floor((pow(2,basefuncmodulationpar3*5.0)-1.0));
+ break;
+ case 3:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*7.0)-1.0)/10.0;
+ basefuncmodulationpar3=0.01+(pow(2,basefuncmodulationpar3*16.0)-1.0)/10.0;
+ break;
+ };
+
+// printf("%.5f %.5f\n",basefuncmodulationpar1,basefuncmodulationpar3);
+
+ for (i=0;i<OSCIL_SIZE;i++) {
+ REALTYPE t=i*1.0/OSCIL_SIZE;
+
+ switch(Pbasefuncmodulation){
+ case 1:t=t*basefuncmodulationpar3+sin((t+basefuncmodulationpar2)*2.0*PI)*basefuncmodulationpar1;//rev
+ break;
+ case 2:t=t+sin((t*basefuncmodulationpar3+basefuncmodulationpar2)*2.0*PI)*basefuncmodulationpar1;//sine
+ break;
+ case 3:t=t+pow((1.0-cos((t+basefuncmodulationpar2)*2.0*PI))*0.5,basefuncmodulationpar3)*basefuncmodulationpar1;//power
+ break;
+ };
+
+ t=t-floor(t);
+
+ switch (Pcurrentbasefunc){
+ case 1:smps[i]=basefunc_triangle(t,par);
+ break;
+ case 2:smps[i]=basefunc_pulse(t,par);
+ break;
+ case 3:smps[i]=basefunc_saw(t,par);
+ break;
+ case 4:smps[i]=basefunc_power(t,par);
+ break;
+ case 5:smps[i]=basefunc_gauss(t,par);
+ break;
+ case 6:smps[i]=basefunc_diode(t,par);
+ break;
+ case 7:smps[i]=basefunc_abssine(t,par);
+ break;
+ case 8:smps[i]=basefunc_pulsesine(t,par);
+ break;
+ case 9:smps[i]=basefunc_stretchsine(t,par);
+ break;
+ case 10:smps[i]=basefunc_chirp(t,par);
+ break;
+ case 11:smps[i]=basefunc_absstretchsine(t,par);
+ break;
+ case 12:smps[i]=basefunc_chebyshev(t,par);
+ break;
+ case 13:smps[i]=basefunc_sqr(t,par);
+ break;
+ default:smps[i]=-sin(2.0*PI*i/OSCIL_SIZE);
+ };
+ };
+};
+
+/*
+ * Filter the oscillator
+ */
+void OscilGen::oscilfilter(){
+ if (Pfiltertype==0) return;
+ REALTYPE par=1.0-Pfilterpar1/128.0;
+ REALTYPE par2=Pfilterpar2/127.0;
+ REALTYPE max=0.0,tmp=0.0,p2,x;
+ for (int i=1;i<OSCIL_SIZE/2;i++){
+ REALTYPE gain=1.0;
+ switch(Pfiltertype){
+ case 1: gain=pow(1.0-par*par*par*0.99,i);//lp
+ tmp=par2*par2*par2*par2*0.5+0.0001;
+ if (gain<tmp) gain=pow(gain,10.0)/pow(tmp,9.0);
+ break;
+ case 2: gain=1.0-pow(1.0-par*par,i+1);//hp1
+ gain=pow(gain,par2*2.0+0.1);
+ break;
+ case 3: if (par<0.2) par=par*0.25+0.15;
+ gain=1.0-pow(1.0-par*par*0.999+0.001,i*0.05*i+1.0);//hp1b
+ tmp=pow(5.0,par2*2.0);
+ gain=pow(gain,tmp);
+ break;
+ case 4: gain=i+1-pow(2,(1.0-par)*7.5);//bp1
+ gain=1.0/(1.0+gain*gain/(i+1.0));
+ tmp=pow(5.0,par2*2.0);
+ gain=pow(gain,tmp);
+ if (gain<1e-5) gain=1e-5;
+ break;
+ case 5: gain=i+1-pow(2,(1.0-par)*7.5);//bs1
+ gain=pow(atan(gain/(i/10.0+1))/1.57,6);
+ gain=pow(gain,par2*par2*3.9+0.1);
+ break;
+ case 6: tmp=pow(par2,0.33);
+ gain=(i+1>pow(2,(1.0-par)*10)?0.0:1.0)*par2+(1.0-par2);//lp2
+ break;
+ case 7: tmp=pow(par2,0.33);
+ //tmp=1.0-(1.0-par2)*(1.0-par2);
+ gain=(i+1>pow(2,(1.0-par)*7)?1.0:0.0)*par2+(1.0-par2);//hp2
+ if (Pfilterpar1==0) gain=1.0;
+ break;
+ case 8: tmp=pow(par2,0.33);
+ //tmp=1.0-(1.0-par2)*(1.0-par2);
+ gain=(fabs(pow(2,(1.0-par)*7)-i)>i/2+1?0.0:1.0)*par2+(1.0-par2);//bp2
+ break;
+ case 9: tmp=pow(par2,0.33);
+ gain=(fabs(pow(2,(1.0-par)*7)-i)<i/2+1?0.0:1.0)*par2+(1.0-par2);//bs2
+ break;
+ case 10:tmp=pow(5.0,par2*2.0-1.0);
+ tmp=pow(i/32.0,tmp)*32.0;
+ if (Pfilterpar2==64) tmp=i;
+ gain=cos(par*par*PI/2.0*tmp);//cos
+ gain*=gain;
+ break;
+ case 11:tmp=pow(5.0,par2*2.0-1.0);
+ tmp=pow(i/32.0,tmp)*32.0;
+ if (Pfilterpar2==64) tmp=i;
+ gain=sin(par*par*PI/2.0*tmp);//sin
+ gain*=gain;
+ break;
+ case 12:p2=1.0-par+0.2;
+ x=i/(64.0*p2*p2);
+ if (x<0.0) x=0.0;
+ else if (x>1.0) x=1.0;
+ tmp=pow(1.0-par2,2.0);
+ gain=cos(x*PI)*(1.0-tmp)+1.01+tmp;//low shelf
+ break;
+ case 13:tmp=(int) (pow(2.0,(1.0-par)*7.2));
+ gain=1.0;
+ if (i==(int) (tmp)) gain=pow(2.0,par2*par2*8.0);
+ break;
+ };
+
+
+ oscilFFTfreqs.s[i]*=gain;
+ oscilFFTfreqs.c[i]*=gain;
+ REALTYPE tmp=oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]+
+ oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i];
+ if (max<tmp) max=tmp;
+ };
+
+ max=sqrt(max);
+ if (max<1e-10) max=1.0;
+ REALTYPE imax=1.0/max;
+ for (int i=1;i<OSCIL_SIZE/2;i++) {
+ oscilFFTfreqs.s[i]*=imax;
+ oscilFFTfreqs.c[i]*=imax;
+ };
+};
+
+/*
+ * Change the base function
+ */
+void OscilGen::changebasefunction(){
+ if (Pcurrentbasefunc!=0) {
+ getbasefunction(tmpsmps);
+ fft->smps2freqs(tmpsmps,basefuncFFTfreqs);
+ basefuncFFTfreqs.c[0]=0.0;
+ } else {
+ for (int i=0;i<OSCIL_SIZE/2;i++){
+ basefuncFFTfreqs.s[i]=0.0;
+ basefuncFFTfreqs.c[i]=0.0;
+ };
+ //in this case basefuncFFTfreqs_ are not used
+ }
+ oscilprepared=0;
+ oldbasefunc=Pcurrentbasefunc;
+ oldbasepar=Pbasefuncpar;
+ oldbasefuncmodulation=Pbasefuncmodulation;
+ oldbasefuncmodulationpar1=Pbasefuncmodulationpar1;
+ oldbasefuncmodulationpar2=Pbasefuncmodulationpar2;
+ oldbasefuncmodulationpar3=Pbasefuncmodulationpar3;
+};
+
+/*
+ * Waveshape
+ */
+void OscilGen::waveshape(){
+ int i;
+
+ oldwaveshapingfunction=Pwaveshapingfunction;
+ oldwaveshaping=Pwaveshaping;
+ if (Pwaveshapingfunction==0) return;
+
+ oscilFFTfreqs.c[0]=0.0;//remove the DC
+ //reduce the amplitude of the freqs near the nyquist
+ for (i=1;i<OSCIL_SIZE/8;i++) {
+ REALTYPE tmp=i/(OSCIL_SIZE/8.0);
+ oscilFFTfreqs.s[OSCIL_SIZE/2-i]*=tmp;
+ oscilFFTfreqs.c[OSCIL_SIZE/2-i]*=tmp;
+ };
+ fft->freqs2smps(oscilFFTfreqs,tmpsmps);
+
+ //Normalize
+ REALTYPE max=0.0;
+ for (i=0;i<OSCIL_SIZE;i++)
+ if (max<fabs(tmpsmps[i])) max=fabs(tmpsmps[i]);
+ if (max<0.00001) max=1.0;
+ max=1.0/max;for (i=0;i<OSCIL_SIZE;i++) tmpsmps[i]*=max;
+
+ //Do the waveshaping
+ waveshapesmps(OSCIL_SIZE,tmpsmps,Pwaveshapingfunction,Pwaveshaping);
+
+ fft->smps2freqs(tmpsmps,oscilFFTfreqs);//perform FFT
+};
+
+
+/*
+ * Do the Frequency Modulation of the Oscil
+ */
+void OscilGen::modulation(){
+ int i;
+
+ oldmodulation=Pmodulation;
+ oldmodulationpar1=Pmodulationpar1;
+ oldmodulationpar2=Pmodulationpar2;
+ oldmodulationpar3=Pmodulationpar3;
+ if (Pmodulation==0) return;
+
+
+ REALTYPE modulationpar1=Pmodulationpar1/127.0,
+ modulationpar2=0.5-Pmodulationpar2/127.0,
+ modulationpar3=Pmodulationpar3/127.0;
+
+ switch(Pmodulation){
+ case 1:modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0;
+ modulationpar3=floor((pow(2,modulationpar3*5.0)-1.0));
+ if (modulationpar3<0.9999) modulationpar3=-1.0;
+ break;
+ case 2:modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0;
+ modulationpar3=1.0+floor((pow(2,modulationpar3*5.0)-1.0));
+ break;
+ case 3:modulationpar1=(pow(2,modulationpar1*9.0)-1.0)/100.0;
+ modulationpar3=0.01+(pow(2,modulationpar3*16.0)-1.0)/10.0;
+ break;
+ };
+
+ oscilFFTfreqs.c[0]=0.0;//remove the DC
+ //reduce the amplitude of the freqs near the nyquist
+ for (i=1;i<OSCIL_SIZE/8;i++) {
+ REALTYPE tmp=i/(OSCIL_SIZE/8.0);
+ oscilFFTfreqs.s[OSCIL_SIZE/2-i]*=tmp;
+ oscilFFTfreqs.c[OSCIL_SIZE/2-i]*=tmp;
+ };
+ fft->freqs2smps(oscilFFTfreqs,tmpsmps);
+ int extra_points=2;
+ REALTYPE *in=new REALTYPE[OSCIL_SIZE+extra_points];
+
+ //Normalize
+ REALTYPE max=0.0;
+ for (i=0;i<OSCIL_SIZE;i++) if (max<fabs(tmpsmps[i])) max=fabs(tmpsmps[i]);
+ if (max<0.00001) max=1.0;
+ max=1.0/max;for (i=0;i<OSCIL_SIZE;i++) in[i]=tmpsmps[i]*max;
+ for (i=0;i<extra_points;i++) in[i+OSCIL_SIZE]=tmpsmps[i]*max;
+
+ //Do the modulation
+ for (i=0;i<OSCIL_SIZE;i++) {
+ REALTYPE t=i*1.0/OSCIL_SIZE;
+
+ switch(Pmodulation){
+ case 1:t=t*modulationpar3+sin((t+modulationpar2)*2.0*PI)*modulationpar1;//rev
+ break;
+ case 2:t=t+sin((t*modulationpar3+modulationpar2)*2.0*PI)*modulationpar1;//sine
+ break;
+ case 3:t=t+pow((1.0-cos((t+modulationpar2)*2.0*PI))*0.5,modulationpar3)*modulationpar1;//power
+ break;
+ };
+
+ t=(t-floor(t))*OSCIL_SIZE;
+
+ int poshi=(int) t;
+ REALTYPE poslo=t-floor(t);
+
+ tmpsmps[i]=in[poshi]*(1.0-poslo)+in[poshi+1]*poslo;
+ };
+
+ delete(in);
+ fft->smps2freqs(tmpsmps,oscilFFTfreqs);//perform FFT
+};
+
+
+
+/*
+ * Adjust the spectrum
+ */
+void OscilGen::spectrumadjust(){
+ if (Psatype==0) return;
+ REALTYPE par=Psapar/127.0;
+ switch(Psatype){
+ case 1: par=1.0-par*2.0;
+ if (par>=0.0) par=pow(5.0,par);
+ else par=pow(8.0,par);
+ break;
+ case 2: par=pow(10.0,(1.0-par)*3.0)*0.25;
+ break;
+ case 3: par=pow(10.0,(1.0-par)*3.0)*0.25;
+ break;
+ };
+
+
+ REALTYPE max=0.0;
+ for (int i=0;i<OSCIL_SIZE/2;i++){
+ REALTYPE tmp=pow(oscilFFTfreqs.c[i],2)+pow(oscilFFTfreqs.s[i],2.0);
+ if (max<tmp) max=tmp;
+ };
+ max=sqrt(max)/OSCIL_SIZE*2.0;
+ if (max<1e-8) max=1.0;
+
+
+ for (int i=0;i<OSCIL_SIZE/2;i++){
+ REALTYPE mag=sqrt(pow(oscilFFTfreqs.s[i],2)+pow(oscilFFTfreqs.c[i],2.0))/max;
+ REALTYPE phase=atan2(oscilFFTfreqs.s[i],oscilFFTfreqs.c[i]);
+
+ switch (Psatype){
+ case 1: mag=pow(mag,par);
+ break;
+ case 2: if (mag<par) mag=0.0;
+ break;
+ case 3: mag/=par;
+ if (mag>1.0) mag=1.0;
+ break;
+ };
+ oscilFFTfreqs.c[i]=mag*cos(phase);
+ oscilFFTfreqs.s[i]=mag*sin(phase);
+ };
+
+};
+
+void OscilGen::shiftharmonics(){
+ if (Pharmonicshift==0) return;
+
+ REALTYPE hc,hs;
+ int harmonicshift=-Pharmonicshift;
+
+ if (harmonicshift>0){
+ for (int i=OSCIL_SIZE/2-2;i>=0;i--){
+ int oldh=i-harmonicshift;
+ if (oldh<0){
+ hc=0.0;
+ hs=0.0;
+ } else {
+ hc=oscilFFTfreqs.c[oldh+1];
+ hs=oscilFFTfreqs.s[oldh+1];
+ };
+ oscilFFTfreqs.c[i+1]=hc;
+ oscilFFTfreqs.s[i+1]=hs;
+ };
+ } else {
+ for (int i=0;i<OSCIL_SIZE/2-1;i++){
+ int oldh=i+abs(harmonicshift);
+ if (oldh>=(OSCIL_SIZE/2-1)){
+ hc=0.0;
+ hs=0.0;
+ } else {
+ hc=oscilFFTfreqs.c[oldh+1];
+ hs=oscilFFTfreqs.s[oldh+1];
+ if (fabs(hc)<0.000001) hc=0.0;
+ if (fabs(hs)<0.000001) hs=0.0;
+ };
+
+ oscilFFTfreqs.c[i+1]=hc;
+ oscilFFTfreqs.s[i+1]=hs;
+ };
+ };
+
+ oscilFFTfreqs.c[0]=0.0;
+};
+
+/*
+ * Prepare the Oscillator
+ */
+void OscilGen::prepare(){
+ int i,j,k;
+ REALTYPE a,b,c,d,hmagnew;
+
+ if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)||
+ (oldbasefuncmodulation!=Pbasefuncmodulation)||
+ (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)||
+ (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)||
+ (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3))
+ changebasefunction();
+
+ for (i=0;i<MAX_AD_HARMONICS;i++) hphase[i]=(Phphase[i]-64.0)/64.0*PI/(i+1);
+
+ for (i=0;i<MAX_AD_HARMONICS;i++){
+ hmagnew=1.0-fabs(Phmag[i]/64.0-1.0);
+ switch(Phmagtype){
+ case 1:hmag[i]=exp(hmagnew*log(0.01)); break;
+ case 2:hmag[i]=exp(hmagnew*log(0.001));break;
+ case 3:hmag[i]=exp(hmagnew*log(0.0001));break;
+ case 4:hmag[i]=exp(hmagnew*log(0.00001));break;
+ default:hmag[i]=1.0-hmagnew;
+ break;
+ };
+
+ if (Phmag[i]<64) hmag[i]=-hmag[i];
+ };
+
+ //remove the harmonics where Phmag[i]==64
+ for (i=0;i<MAX_AD_HARMONICS;i++) if (Phmag[i]==64) hmag[i]=0.0;
+
+
+ for (i=0;i<OSCIL_SIZE/2;i++) {
+ oscilFFTfreqs.c[i]=0.0;
+ oscilFFTfreqs.s[i]=0.0;
+ };
+ if (Pcurrentbasefunc==0) {//the sine case
+ for (i=0;i<MAX_AD_HARMONICS;i++){
+ oscilFFTfreqs.c[i+1]=-hmag[i]*sin(hphase[i]*(i+1))/2.0;
+ oscilFFTfreqs.s[i+1]=hmag[i]*cos(hphase[i]*(i+1))/2.0;
+ };
+ } else {
+ for (j=0;j<MAX_AD_HARMONICS;j++){
+ if (Phmag[j]==64) continue;
+ for (i=1;i<OSCIL_SIZE/2;i++){
+ k=i*(j+1);if (k>=OSCIL_SIZE/2) break;
+ a=basefuncFFTfreqs.c[i];
+ b=basefuncFFTfreqs.s[i];
+ c=hmag[j]*cos(hphase[j]*k);
+ d=hmag[j]*sin(hphase[j]*k);
+ oscilFFTfreqs.c[k]+=a*c-b*d;
+ oscilFFTfreqs.s[k]+=a*d+b*c;
+ };
+ };
+
+ };
+
+ if (Pharmonicshiftfirst!=0) shiftharmonics();
+
+
+
+ if (Pfilterbeforews==0){
+ waveshape();
+ oscilfilter();
+ } else {
+ oscilfilter();
+ waveshape();
+ };
+
+ modulation();
+ spectrumadjust();
+ if (Pharmonicshiftfirst==0) shiftharmonics();
+
+ oscilFFTfreqs.c[0]=0.0;
+
+ oldhmagtype=Phmagtype;
+ oldharmonicshift=Pharmonicshift+Pharmonicshiftfirst*256;
+
+ oscilprepared=1;
+};
+
+void OscilGen::adaptiveharmonic(FFTFREQS f,REALTYPE freq){
+ if ((Padaptiveharmonics==0)/*||(freq<1.0)*/) return;
+ if (freq<1.0) freq=440.0;
+
+ FFTFREQS inf;
+ newFFTFREQS(&inf,OSCIL_SIZE/2);
+ for (int i=0;i<OSCIL_SIZE/2;i++) {
+ inf.s[i]=f.s[i];
+ inf.c[i]=f.c[i];
+ f.s[i]=0.0;
+ f.c[i]=0.0;
+ };
+ inf.c[0]=0.0;inf.s[0]=0.0;
+
+ REALTYPE hc=0.0,hs=0.0;
+ REALTYPE basefreq=30.0*pow(10.0,Padaptiveharmonicsbasefreq/128.0);
+ REALTYPE power=(Padaptiveharmonicspower+1.0)/101.0;
+
+ REALTYPE rap=freq/basefreq;
+
+ rap=pow(rap,power);
+
+ bool down=false;
+ if (rap>1.0) {
+ rap=1.0/rap;
+ down=true;
+ };
+
+ for (int i=0;i<OSCIL_SIZE/2-2;i++){
+ REALTYPE h=i*rap;
+ int high=(int)(i*rap);
+ REALTYPE low=fmod(h,1.0);
+
+ if (high>=(OSCIL_SIZE/2-2)){
+ break;
+ } else {
+ if (down){
+ f.c[high]+=inf.c[i]*(1.0-low);
+ f.s[high]+=inf.s[i]*(1.0-low);
+ f.c[high+1]+=inf.c[i]*low;
+ f.s[high+1]+=inf.s[i]*low;
+ } else {
+ hc=inf.c[high]*(1.0-low)+inf.c[high+1]*low;
+ hs=inf.s[high]*(1.0-low)+inf.s[high+1]*low;
+ };
+ if (fabs(hc)<0.000001) hc=0.0;
+ if (fabs(hs)<0.000001) hs=0.0;
+ };
+
+ if (!down){
+ if (i==0) {//corect the aplitude of the first harmonic
+ hc*=rap;
+ hs*=rap;
+ };
+ f.c[i]=hc;
+ f.s[i]=hs;
+ };
+ };
+
+ f.c[1]+=f.c[0];f.s[1]+=f.s[0];
+ f.c[0]=0.0;f.s[0]=0.0;
+ deleteFFTFREQS(&inf);
+};
+
+void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f,int size){
+ if (Padaptiveharmonics<=1) return;
+ REALTYPE *inf=new REALTYPE[size];
+ REALTYPE par=Padaptiveharmonicspar*0.01;
+ par=1.0-pow((1.0-par),1.5);
+
+ for (int i=0;i<size;i++) {
+ inf[i]=f[i]*par;
+ f[i]=f[i]*(1.0-par);
+ };
+
+
+ if (Padaptiveharmonics==2){//2n+1
+ for (int i=0;i<size;i++) if ((i%2)==0) f[i]+=inf[i];//i=0 pt prima armonica,etc.
+ } else{//celelalte moduri
+ int nh=(Padaptiveharmonics-3)/2+2;
+ int sub_vs_add=(Padaptiveharmonics-3)%2;
+ if (sub_vs_add==0){
+ for (int i=0;i<size;i++) {
+ if (((i+1)%nh)==0){
+ f[i]+=inf[i];
+ };
+ };
+ } else {
+ for (int i=0;i<size/nh-1;i++) {
+ f[(i+1)*nh-1]+=inf[i];
+ };
+ };
+ };
+
+ delete(inf);
+};
+
+
+
+/*
+ * Get the oscillator function
+ */
+short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz){
+ return(this->get(smps,freqHz,0));
+};
+
+void OscilGen::newrandseed(unsigned int randseed){
+ this->randseed=randseed;
+};
+
+/*
+ * Get the oscillator function
+ */
+short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz,int resonance){
+ int i;
+ int nyquist,outpos;
+
+ if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)||(oldhmagtype!=Phmagtype)
+ ||(oldwaveshaping!=Pwaveshaping)||(oldwaveshapingfunction!=Pwaveshapingfunction)) oscilprepared=0;
+ if (oldfilterpars!=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216){
+ oscilprepared=0;
+ oldfilterpars=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216;
+ };
+ if (oldsapars!=Psatype*256+Psapar){
+ oscilprepared=0;
+ oldsapars=Psatype*256+Psapar;
+ };
+
+ if ((oldbasefuncmodulation!=Pbasefuncmodulation)||
+ (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)||
+ (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)||
+ (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3))
+ oscilprepared=0;
+
+ if ((oldmodulation!=Pmodulation)||
+ (oldmodulationpar1!=Pmodulationpar1)||
+ (oldmodulationpar2!=Pmodulationpar2)||
+ (oldmodulationpar3!=Pmodulationpar3))
+ oscilprepared=0;
+
+ if (oldharmonicshift!=Pharmonicshift+Pharmonicshiftfirst*256) oscilprepared=0;
+
+ if (oscilprepared!=1) prepare();
+
+ outpos=(int)((RND*2.0-1.0)*(REALTYPE) OSCIL_SIZE*(Prand-64.0)/64.0);
+ outpos=(outpos+2*OSCIL_SIZE) % OSCIL_SIZE;
+
+
+ for (i=0;i<OSCIL_SIZE/2;i++){
+ outoscilFFTfreqs.c[i]=0.0;
+ outoscilFFTfreqs.s[i]=0.0;
+ };
+
+ nyquist=(int)(0.5*SAMPLE_RATE/fabs(freqHz))+2;
+ if (ADvsPAD) nyquist=(int)(OSCIL_SIZE/2);
+ if (nyquist>OSCIL_SIZE/2) nyquist=OSCIL_SIZE/2;
+
+
+ int realnyquist=nyquist;
+
+ if (Padaptiveharmonics!=0) nyquist=OSCIL_SIZE/2;
+ for (i=1;i<nyquist-1;i++) {
+ outoscilFFTfreqs.c[i]=oscilFFTfreqs.c[i];
+ outoscilFFTfreqs.s[i]=oscilFFTfreqs.s[i];
+ };
+
+ adaptiveharmonic(outoscilFFTfreqs,freqHz);
+ adaptiveharmonicpostprocess(&outoscilFFTfreqs.c[1],OSCIL_SIZE/2-1);
+ adaptiveharmonicpostprocess(&outoscilFFTfreqs.s[1],OSCIL_SIZE/2-1);
+
+ nyquist=realnyquist;
+ if (Padaptiveharmonics){//do the antialiasing in the case of adaptive harmonics
+ for (i=nyquist;i<OSCIL_SIZE/2;i++) {
+ outoscilFFTfreqs.s[i]=0;
+ outoscilFFTfreqs.c[i]=0;
+ };
+ };
+
+ // Randomness (each harmonic), the block type is computed
+ // in ADnote by setting start position according to this setting
+ if ((Prand>64)&&(freqHz>=0.0)&&(!ADvsPAD)){
+ REALTYPE rnd,angle,a,b,c,d;
+ rnd=PI*pow((Prand-64.0)/64.0,2.0);
+ for (i=1;i<nyquist-1;i++){//to Nyquist only for AntiAliasing
+ angle=rnd*i*RND;
+ a=outoscilFFTfreqs.c[i];
+ b=outoscilFFTfreqs.s[i];
+ c=cos(angle);
+ d=sin(angle);
+ outoscilFFTfreqs.c[i]=a*c-b*d;
+ outoscilFFTfreqs.s[i]=a*d+b*c;
+ };
+ };
+
+ //Harmonic Amplitude Randomness
+ if ((freqHz>0.1)&&(!ADvsPAD)) {
+ unsigned int realrnd=rand();
+ srand(randseed);
+ REALTYPE power=Pamprandpower/127.0;
+ REALTYPE normalize=1.0/(1.2-power);
+ switch (Pamprandtype){
+ case 1: power=power*2.0-0.5;
+ power=pow(15.0,power);
+ for (i=1;i<nyquist-1;i++){
+ REALTYPE amp=pow(RND,power)*normalize;
+ outoscilFFTfreqs.c[i]*=amp;
+ outoscilFFTfreqs.s[i]*=amp;
+ };
+ break;
+ case 2: power=power*2.0-0.5;
+ power=pow(15.0,power)*2.0;
+ REALTYPE rndfreq=2*PI*RND;
+ for (i=1;i<nyquist-1;i++){
+ REALTYPE amp=pow(fabs(sin(i*rndfreq)),power)*normalize;
+ outoscilFFTfreqs.c[i]*=amp;
+ outoscilFFTfreqs.s[i]*=amp;
+ };
+ break;
+ };
+ srand(realrnd+1);
+ };
+
+ if ((freqHz>0.1)&&(resonance!=0)) res->applyres(nyquist-1,outoscilFFTfreqs,freqHz);
+
+ //Full RMS normalize
+ REALTYPE sum=0;
+ for (int j=1;j<OSCIL_SIZE/2;j++) {
+ REALTYPE term=outoscilFFTfreqs.c[j]*outoscilFFTfreqs.c[j]
+ +outoscilFFTfreqs.s[j]*outoscilFFTfreqs.s[j];
+ sum+=term;
+ };
+ if (sum<0.000001) sum=1.0;
+ sum=1.0/sqrt(sum);
+ for (int j=1;j<OSCIL_SIZE/2;j++) {
+ outoscilFFTfreqs.c[j]*=sum;
+ outoscilFFTfreqs.s[j]*=sum;
+ };
+
+
+ if ((ADvsPAD)&&(freqHz>0.1)){//in this case the smps will contain the freqs
+ for (i=1;i<OSCIL_SIZE/2;i++) smps[i-1]=sqrt(outoscilFFTfreqs.c[i]*outoscilFFTfreqs.c[i]
+ +outoscilFFTfreqs.s[i]*outoscilFFTfreqs.s[i]);
+ } else {
+ fft->freqs2smps(outoscilFFTfreqs,smps);
+ for (i=0;i<OSCIL_SIZE;i++) smps[i]*=0.25;//correct the amplitude
+ };
+
+ if (Prand<64) return(outpos);
+ else return(0);
+};
+
+
+/*
+ * Get the spectrum of the oscillator for the UI
+ */
+void OscilGen::getspectrum(int n, REALTYPE *spc,int what){
+ if (n>OSCIL_SIZE/2) n=OSCIL_SIZE/2;
+
+ for (int i=1;i<n;i++){
+ if (what==0){
+ spc[i-1]=sqrt(oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i]
+ +oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]);
+ } else {
+ if (Pcurrentbasefunc==0) spc[i-1]=((i==1)?(1.0):(0.0));
+ else spc[i-1]=sqrt(basefuncFFTfreqs.c[i]*basefuncFFTfreqs.c[i]+
+ basefuncFFTfreqs.s[i]*basefuncFFTfreqs.s[i]);
+ };
+ };
+
+ if (what==0) {
+ for (int i=0;i<n;i++) outoscilFFTfreqs.s[i]=outoscilFFTfreqs.c[i]=spc[i+1];
+ for (int i=n;i<OSCIL_SIZE/2;i++) outoscilFFTfreqs.s[i]=outoscilFFTfreqs.c[i]=0.0;
+ adaptiveharmonic(outoscilFFTfreqs,0.0);
+ for (int i=1;i<n;i++) spc[i-1]=outoscilFFTfreqs.s[i];
+ adaptiveharmonicpostprocess(spc,n-1);
+ };
+};
+
+
+/*
+ * Convert the oscillator as base function
+ */
+void OscilGen::useasbase(){
+ int i;
+
+ for (i=0;i<OSCIL_SIZE/2;i++) {
+ basefuncFFTfreqs.c[i]=oscilFFTfreqs.c[i];
+ basefuncFFTfreqs.s[i]=oscilFFTfreqs.s[i];
+ };
+
+ oldbasefunc=Pcurrentbasefunc=127;
+
+ prepare();
+};
+
+
+/*
+ * Get the base function for UI
+ */
+void OscilGen::getcurrentbasefunction(REALTYPE *smps){
+ if (Pcurrentbasefunc!=0) {
+ fft->freqs2smps(basefuncFFTfreqs,smps);
+ } else getbasefunction(smps);//the sine case
+};
+
+
+void OscilGen::add2XML(XMLwrapper *xml){
+ xml->addpar("harmonic_mag_type",Phmagtype);
+
+ xml->addpar("base_function",Pcurrentbasefunc);
+ xml->addpar("base_function_par",Pbasefuncpar);
+ xml->addpar("base_function_modulation",Pbasefuncmodulation);
+ xml->addpar("base_function_modulation_par1",Pbasefuncmodulationpar1);
+ xml->addpar("base_function_modulation_par2",Pbasefuncmodulationpar2);
+ xml->addpar("base_function_modulation_par3",Pbasefuncmodulationpar3);
+
+ xml->addpar("modulation",Pmodulation);
+ xml->addpar("modulation_par1",Pmodulationpar1);
+ xml->addpar("modulation_par2",Pmodulationpar2);
+ xml->addpar("modulation_par3",Pmodulationpar3);
+
+ xml->addpar("wave_shaping",Pwaveshaping);
+ xml->addpar("wave_shaping_function",Pwaveshapingfunction);
+
+ xml->addpar("filter_type",Pfiltertype);
+ xml->addpar("filter_par1",Pfilterpar1);
+ xml->addpar("filter_par2",Pfilterpar2);
+ xml->addpar("filter_before_wave_shaping",Pfilterbeforews);
+
+ xml->addpar("spectrum_adjust_type",Psatype);
+ xml->addpar("spectrum_adjust_par",Psapar);
+
+ xml->addpar("rand",Prand);
+ xml->addpar("amp_rand_type",Pamprandtype);
+ xml->addpar("amp_rand_power",Pamprandpower);
+
+ xml->addpar("harmonic_shift",Pharmonicshift);
+ xml->addparbool("harmonic_shift_first",Pharmonicshiftfirst);
+
+ xml->addpar("adaptive_harmonics",Padaptiveharmonics);
+ xml->addpar("adaptive_harmonics_base_frequency",Padaptiveharmonicsbasefreq);
+ xml->addpar("adaptive_harmonics_power",Padaptiveharmonicspower);
+
+ xml->beginbranch("HARMONICS");
+ for (int n=0;n<MAX_AD_HARMONICS;n++){
+ if ((Phmag[n]==64)&&(Phphase[n]==64)) continue;
+ xml->beginbranch("HARMONIC",n+1);
+ xml->addpar("mag",Phmag[n]);
+ xml->addpar("phase",Phphase[n]);
+ xml->endbranch();
+ };
+ xml->endbranch();
+
+ if (Pcurrentbasefunc==127){
+ REALTYPE max=0.0;
+
+ for (int i=0;i<OSCIL_SIZE/2;i++){
+ if (max<fabs(basefuncFFTfreqs.c[i])) max=fabs(basefuncFFTfreqs.c[i]);
+ if (max<fabs(basefuncFFTfreqs.s[i])) max=fabs(basefuncFFTfreqs.s[i]);
+ };
+ if (max<0.00000001) max=1.0;
+
+ xml->beginbranch("BASE_FUNCTION");
+ for (int i=1;i<OSCIL_SIZE/2;i++){
+ REALTYPE xc=basefuncFFTfreqs.c[i]/max;
+ REALTYPE xs=basefuncFFTfreqs.s[i]/max;
+ if ((fabs(xs)>0.00001)&&(fabs(xs)>0.00001)){
+ xml->beginbranch("BF_HARMONIC",i);
+ xml->addparreal("cos",xc);
+ xml->addparreal("sin",xs);
+ xml->endbranch();
+ };
+ };
+ xml->endbranch();
+ };
+};
+
+
+void OscilGen::getfromXML(XMLwrapper *xml){
+
+ Phmagtype=xml->getpar127("harmonic_mag_type",Phmagtype);
+
+ Pcurrentbasefunc=xml->getpar127("base_function",Pcurrentbasefunc);
+ Pbasefuncpar=xml->getpar127("base_function_par",Pbasefuncpar);
+
+ Pbasefuncmodulation=xml->getpar127("base_function_modulation",Pbasefuncmodulation);
+ Pbasefuncmodulationpar1=xml->getpar127("base_function_modulation_par1",Pbasefuncmodulationpar1);
+ Pbasefuncmodulationpar2=xml->getpar127("base_function_modulation_par2",Pbasefuncmodulationpar2);
+ Pbasefuncmodulationpar3=xml->getpar127("base_function_modulation_par3",Pbasefuncmodulationpar3);
+
+ Pmodulation=xml->getpar127("modulation",Pmodulation);
+ Pmodulationpar1=xml->getpar127("modulation_par1",Pmodulationpar1);
+ Pmodulationpar2=xml->getpar127("modulation_par2",Pmodulationpar2);
+ Pmodulationpar3=xml->getpar127("modulation_par3",Pmodulationpar3);
+
+ Pwaveshaping=xml->getpar127("wave_shaping",Pwaveshaping);
+ Pwaveshapingfunction=xml->getpar127("wave_shaping_function",Pwaveshapingfunction);
+
+ Pfiltertype=xml->getpar127("filter_type",Pfiltertype);
+ Pfilterpar1=xml->getpar127("filter_par1",Pfilterpar1);
+ Pfilterpar2=xml->getpar127("filter_par2",Pfilterpar2);
+ Pfilterbeforews=xml->getpar127("filter_before_wave_shaping",Pfilterbeforews);
+
+ Psatype=xml->getpar127("spectrum_adjust_type",Psatype);
+ Psapar=xml->getpar127("spectrum_adjust_par",Psapar);
+
+ Prand=xml->getpar127("rand",Prand);
+ Pamprandtype=xml->getpar127("amp_rand_type",Pamprandtype);
+ Pamprandpower=xml->getpar127("amp_rand_power",Pamprandpower);
+
+ Pharmonicshift=xml->getpar("harmonic_shift",Pharmonicshift,-64,64);
+ Pharmonicshiftfirst=xml->getparbool("harmonic_shift_first",Pharmonicshiftfirst);
+
+ Padaptiveharmonics=xml->getpar("adaptive_harmonics",Padaptiveharmonics,0,127);
+ Padaptiveharmonicsbasefreq=xml->getpar("adaptive_harmonics_base_frequency",Padaptiveharmonicsbasefreq,0,255);
+ Padaptiveharmonicspower=xml->getpar("adaptive_harmonics_power",Padaptiveharmonicspower,0,200);
+
+
+ if (xml->enterbranch("HARMONICS")){
+ Phmag[0]=64;Phphase[0]=64;
+ for (int n=0;n<MAX_AD_HARMONICS;n++){
+ if (xml->enterbranch("HARMONIC",n+1)==0) continue;
+ Phmag[n]=xml->getpar127("mag",64);
+ Phphase[n]=xml->getpar127("phase",64);
+ xml->exitbranch();
+ };
+ xml->exitbranch();
+ };
+
+ if (Pcurrentbasefunc!=0) changebasefunction();
+
+
+ if (xml->enterbranch("BASE_FUNCTION")){
+ for (int i=1;i<OSCIL_SIZE/2;i++){
+ if (xml->enterbranch("BF_HARMONIC",i)){
+ basefuncFFTfreqs.c[i]=xml->getparreal("cos",0.0);
+ basefuncFFTfreqs.s[i]=xml->getparreal("sin",0.0);
+ xml->exitbranch();
+ };
+
+
+ };
+ xml->exitbranch();
+
+ REALTYPE max=0.0;
+
+ basefuncFFTfreqs.c[0]=0.0;
+ for (int i=0;i<OSCIL_SIZE/2;i++) {
+ if (max<fabs(basefuncFFTfreqs.c[i])) max=fabs(basefuncFFTfreqs.c[i]);
+ if (max<fabs(basefuncFFTfreqs.s[i])) max=fabs(basefuncFFTfreqs.s[i]);
+ };
+ if (max<0.00000001) max=1.0;
+
+ for (int i=0;i<OSCIL_SIZE/2;i++) {
+ if (basefuncFFTfreqs.c[i]) basefuncFFTfreqs.c[i]/=max;
+ if (basefuncFFTfreqs.s[i]) basefuncFFTfreqs.s[i]/=max;
+ };
+ };
+};
+
+
+
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/OscilGen.h b/muse_qt4_evolution/synti/zynaddsubfx/Synth/OscilGen.h
new file mode 100644
index 00000000..1d9980a9
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/OscilGen.h
@@ -0,0 +1,176 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ OscilGen.h - Waveform generator for ADnote
+ 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 OSCIL_GEN_H
+#define OSCIL_GEN_H
+
+#include "../globals.h"
+#include "../Misc/XMLwrapper.h"
+#include "Resonance.h"
+#include "../DSP/FFTwrapper.h"
+#include "../Params/Presets.h"
+
+class OscilGen:public Presets{
+ public:
+ OscilGen(FFTwrapper *fft_,Resonance *res_);
+ ~OscilGen();
+
+ //computes the full spectrum of oscil from harmonics,phases and basefunc
+ void prepare();
+
+ //do the antialiasing(cut off higher freqs.),apply randomness and do a IFFT
+ short get(REALTYPE *smps,REALTYPE freqHz);//returns where should I start getting samples, used in block type randomness
+ short get(REALTYPE *smps,REALTYPE freqHz,int resonance);
+ //if freqHz is smaller than 0, return the "un-randomized" sample for UI
+
+ void getbasefunction(REALTYPE *smps);
+
+ //called by UI
+ void getspectrum(int n,REALTYPE *spc,int what);//what=0 pt. oscil,1 pt. basefunc
+ void getcurrentbasefunction(REALTYPE *smps);
+ void useasbase();//convert oscil to base function
+
+ void add2XML(XMLwrapper *xml);
+ void defaults();
+ void getfromXML(XMLwrapper *xml);
+
+ void convert2sine(int magtype);
+
+ //Parameters
+
+ /*
+ The hmag and hphase starts counting from 0, so the first harmonic(1) has the index 0,
+ 2-nd harmonic has index 1, ..the 128 harminic has index 127
+ */
+ unsigned char Phmag[MAX_AD_HARMONICS],Phphase[MAX_AD_HARMONICS];//the MIDI parameters for mag. and phases
+
+
+ /*The Type of magnitude:
+ 0 - Linear
+ 1 - dB scale (-40)
+ 2 - dB scale (-60)
+ 3 - dB scale (-80)
+ 4 - dB scale (-100)*/
+ unsigned char Phmagtype;
+
+ unsigned char Pcurrentbasefunc;//The base function used - 0=sin, 1=...
+ unsigned char Pbasefuncpar;//the parameter of the base function
+
+ unsigned char Pbasefuncmodulation;//what modulation is applied to the basefunc
+ unsigned char Pbasefuncmodulationpar1,Pbasefuncmodulationpar2,Pbasefuncmodulationpar3;//the parameter of the base function modulation
+
+ /*the Randomness:
+ 64=no randomness
+ 63..0 - block type randomness - 0 is maximum
+ 65..127 - each harmonic randomness - 127 is maximum*/
+ unsigned char Prand;
+ unsigned char Pwaveshaping,Pwaveshapingfunction;
+ unsigned char Pfiltertype,Pfilterpar1,Pfilterpar2;
+ unsigned char Pfilterbeforews;
+ unsigned char Psatype,Psapar;//spectrum adjust
+
+ unsigned char Pamprandpower, Pamprandtype;//amplitude randomness
+ int Pharmonicshift;//how the harmonics are shifted
+ int Pharmonicshiftfirst;//if the harmonic shift is done before waveshaping and filter
+
+ unsigned char Padaptiveharmonics;//the adaptive harmonics status (off=0,on=1,etc..)
+ unsigned char Padaptiveharmonicsbasefreq;//the base frequency of the adaptive harmonic (30..3000Hz)
+ unsigned char Padaptiveharmonicspower;//the strength of the effect (0=off,100=full)
+ unsigned char Padaptiveharmonicspar;//the parameters in 2,3,4.. modes of adaptive harmonics
+
+ unsigned char Pmodulation;//what modulation is applied to the oscil
+ unsigned char Pmodulationpar1,Pmodulationpar2,Pmodulationpar3;//the parameter of the parameters
+
+
+ //makes a new random seed for Amplitude Randomness
+ //this should be called every note on event
+ void newrandseed(unsigned int randseed);
+
+ bool ADvsPAD;//if it is used by ADsynth or by PADsynth
+
+ static REALTYPE *tmpsmps;//this array stores some termporary data and it has SOUND_BUFFER_SIZE elements
+ static FFTFREQS outoscilFFTfreqs;
+
+ private:
+
+ REALTYPE hmag[MAX_AD_HARMONICS],hphase[MAX_AD_HARMONICS];//the magnituides and the phases of the sine/nonsine harmonics
+// private:
+ FFTwrapper *fft;
+ //computes the basefunction and make the FFT; newbasefunc<0 = same basefunc
+ void changebasefunction();
+ //Waveshaping
+ void waveshape();
+
+ //Filter the oscillator accotding to Pfiltertype and Pfilterpar
+ void oscilfilter();
+
+ //Adjust the spectrum
+ void spectrumadjust();
+
+ //Shift the harmonics
+ void shiftharmonics();
+
+ //Do the oscil modulation stuff
+ void modulation();
+
+ //Do the adaptive harmonic stuff
+ void adaptiveharmonic(FFTFREQS f,REALTYPE freq);
+
+ //Do the adaptive harmonic postprocessing (2n+1,2xS,2xA,etc..)
+ //this function is called even for the user interface
+ //this can be called for the sine and components, and for the spectrum
+ //(that's why the sine and cosine components should be processed with a separate call)
+ void adaptiveharmonicpostprocess(REALTYPE *f, int size);
+
+ //Basic/base functions (Functiile De Baza)
+ REALTYPE basefunc_pulse(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_saw(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_triangle(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_power(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_gauss(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_diode(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_abssine(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_pulsesine(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_stretchsine(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_chirp(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_absstretchsine(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_chebyshev(REALTYPE x,REALTYPE a);
+ REALTYPE basefunc_sqr(REALTYPE x,REALTYPE a);
+
+ //Internal Data
+ unsigned char oldbasefunc,oldbasepar,oldhmagtype,oldwaveshapingfunction,oldwaveshaping;
+ int oldfilterpars,oldsapars,oldbasefuncmodulation,oldbasefuncmodulationpar1,oldbasefuncmodulationpar2,oldbasefuncmodulationpar3,oldharmonicshift;
+ int oldmodulation,oldmodulationpar1,oldmodulationpar2,oldmodulationpar3;
+
+
+ FFTFREQS basefuncFFTfreqs;//Base Function Frequencies
+ FFTFREQS oscilFFTfreqs;//Oscillator Frequencies - this is different than the hamonics set-up by the user, it may contains time-domain data if the antialiasing is turned off
+ int oscilprepared;//1 if the oscil is prepared, 0 if it is not prepared and is need to call ::prepare() before ::get()
+
+ Resonance *res;
+
+ unsigned int randseed;
+
+};
+
+
+#endif
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/PADnote.C b/muse_qt4_evolution/synti/zynaddsubfx/Synth/PADnote.C
new file mode 100644
index 00000000..9ecc8877
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/PADnote.C
@@ -0,0 +1,342 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PADnote.C - The "pad" 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 <math.h>
+#include "PADnote.h"
+#include "../Misc/Config.h"
+
+PADnote::PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote){
+ ready=0;
+ pars=parameters;
+ portamento=portamento_;
+ ctl=ctl_;
+ this->velocity=velocity;
+ finished_=false;
+
+
+ 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);
+ };
+
+ };
+
+ firsttime=true;
+ released=false;
+ realfreq=basefreq;
+ NoteGlobalPar.Detune=getdetune(pars->PDetuneType
+ ,pars->PCoarseDetune,pars->PDetune);
+
+
+ //find out the closest note
+ REALTYPE logfreq=log(basefreq*pow(2.0,NoteGlobalPar.Detune/1200.0));
+ REALTYPE mindist=fabs(logfreq-log(pars->sample[0].basefreq+0.0001));
+ nsample=0;
+ for (int i=1;i<PAD_MAX_SAMPLES;i++){
+ if (pars->sample[i].smp==NULL) break;
+ REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001));
+// printf("(mindist=%g) %i %g %g\n",mindist,i,dist,pars->sample[i].basefreq);
+
+ if (dist<mindist){
+ nsample=i;
+ mindist=dist;
+ };
+ };
+
+ int size=pars->sample[nsample].size;
+ if (size==0) size=1;
+
+
+ poshi_l=(int)(RND*(size-1));
+ if (pars->PStereo!=0) poshi_r=(poshi_l+size/2)%size;
+ else poshi_r=poshi_l;
+ poslo=0.0;
+
+ tmpwave=new REALTYPE [SOUND_BUFFER_SIZE];
+
+
+
+ if (pars->PPanning==0) NoteGlobalPar.Panning=RND;
+ else NoteGlobalPar.Panning=pars->PPanning/128.0;
+
+ NoteGlobalPar.FilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq
+ pars->PFilterVelocityScale/127.0*6.0* //velocity sensing
+ (VelF(velocity,pars->PFilterVelocityScaleFunction)-1);
+
+ if (pars->PPunchStrength!=0) {
+ NoteGlobalPar.Punch.Enabled=1;
+ NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0
+ NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->PPunchStrength/127.0)-1.0)
+ *VelF(velocity,pars->PPunchVelocitySensing) );
+ REALTYPE time=pow(10,3.0*pars->PPunchTime/127.0)/10000.0;//0.1 .. 100 ms
+ REALTYPE stretch=pow(440.0/freq,pars->PPunchStretch/64.0);
+ NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch);
+ } else NoteGlobalPar.Punch.Enabled=0;
+
+
+
+ NoteGlobalPar.FreqEnvelope=new Envelope(pars->FreqEnvelope,basefreq);
+ NoteGlobalPar.FreqLfo=new LFO(pars->FreqLfo,basefreq);
+
+ NoteGlobalPar.AmpEnvelope=new Envelope(pars->AmpEnvelope,basefreq);
+ NoteGlobalPar.AmpLfo=new LFO(pars->AmpLfo,basefreq);
+
+ NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-pars->PVolume/96.0))//-60 dB .. 0 dB
+ *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing
+
+ NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output
+ globaloldamplitude=globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout();
+
+ NoteGlobalPar.GlobalFilterL=new Filter(pars->GlobalFilter);
+ NoteGlobalPar.GlobalFilterR=new Filter(pars->GlobalFilter);
+
+ NoteGlobalPar.FilterEnvelope=new Envelope(pars->FilterEnvelope,basefreq);
+ NoteGlobalPar.FilterLfo=new LFO(pars->FilterLfo,basefreq);
+ NoteGlobalPar.FilterQ=pars->GlobalFilter->getq();
+ NoteGlobalPar.FilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq);
+
+ ready=1;///sa il pun pe asta doar cand e chiar gata
+
+ if (parameters->sample[nsample].smp==NULL){
+ finished_=true;
+ return;
+ };
+};
+
+PADnote::~PADnote(){
+ delete (NoteGlobalPar.FreqEnvelope);
+ delete (NoteGlobalPar.FreqLfo);
+ delete (NoteGlobalPar.AmpEnvelope);
+ delete (NoteGlobalPar.AmpLfo);
+ delete (NoteGlobalPar.GlobalFilterL);
+ delete (NoteGlobalPar.GlobalFilterR);
+ delete (NoteGlobalPar.FilterEnvelope);
+ delete (NoteGlobalPar.FilterLfo);
+ delete (tmpwave);
+};
+
+
+inline void PADnote::fadein(REALTYPE *smps){
+ int zerocrossings=0;
+ for (int i=1;i<SOUND_BUFFER_SIZE;i++)
+ if ((smps[i-1]<0.0) && (smps[i]>0.0)) zerocrossings++;//this is only the possitive crossings
+
+ REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0;
+ if (tmp<8.0) tmp=8.0;
+
+ int n;
+ F2I(tmp,n);//how many samples is the fade-in
+ if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE;
+ for (int i=0;i<n;i++) {//fade-in
+ REALTYPE tmp=0.5-cos((REALTYPE)i/(REALTYPE) n*PI)*0.5;
+ smps[i]*=tmp;
+ };
+};
+
+
+void PADnote::computecurrentparameters(){
+ REALTYPE globalpitch,globalfilterpitch;
+ globalpitch=0.01*(NoteGlobalPar.FreqEnvelope->envout()+
+ NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod+NoteGlobalPar.Detune);
+ globaloldamplitude=globalnewamplitude;
+ globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout();
+
+ globalfilterpitch=NoteGlobalPar.FilterEnvelope->envout()+NoteGlobalPar.FilterLfo->lfoout()
+ +NoteGlobalPar.FilterCenterPitch;
+
+ REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq
+ +NoteGlobalPar.FilterFreqTracking;
+
+ tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq);
+
+ REALTYPE globalfilterq=NoteGlobalPar.FilterQ*ctl->filterq.relq;
+ NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq,globalfilterq);
+ NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq,globalfilterq);
+
+ //compute the portamento, if it is used by this note
+ REALTYPE portamentofreqrap=1.0;
+ if (portamento!=0){//this voice use portamento
+ portamentofreqrap=ctl->portamento.freqrap;
+ if (ctl->portamento.used==0){//the portamento has finished
+ portamento=0;//this note is no longer "portamented"
+ };
+ };
+
+ realfreq=basefreq*portamentofreqrap*pow(2.0,globalpitch/12.0)*ctl->pitchwheel.relfreq;
+};
+
+
+int PADnote::Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo){
+ REALTYPE *smps=pars->sample[nsample].smp;
+ if (smps==NULL){
+ finished_=true;
+ return(1);
+ };
+ int size=pars->sample[nsample].size;
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++){
+ poshi_l+=freqhi;
+ poshi_r+=freqhi;
+ poslo+=freqlo;
+ if (poslo>=1.0){
+ poshi_l+=1;
+ poshi_r+=1;
+ poslo-=1.0;
+ };
+ if (poshi_l>=size) poshi_l%=size;
+ if (poshi_r>=size) poshi_r%=size;
+
+ outl[i]=smps[poshi_l]*(1.0-poslo)+smps[poshi_l+1]*poslo;
+ outr[i]=smps[poshi_r]*(1.0-poslo)+smps[poshi_r+1]*poslo;
+ };
+ return(1);
+};
+int PADnote::Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo){
+ REALTYPE *smps=pars->sample[nsample].smp;
+ if (smps==NULL){
+ finished_=true;
+ return(1);
+ };
+ int size=pars->sample[nsample].size;
+ REALTYPE xm1,x0,x1,x2,a,b,c;
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++){
+ poshi_l+=freqhi;
+ poshi_r+=freqhi;
+ poslo+=freqlo;
+ if (poslo>=1.0){
+ poshi_l+=1;
+ poshi_r+=1;
+ poslo-=1.0;
+ };
+ if (poshi_l>=size) poshi_l%=size;
+ if (poshi_r>=size) poshi_r%=size;
+
+
+ //left
+ xm1=smps[poshi_l];
+ x0=smps[poshi_l + 1];
+ x1=smps[poshi_l + 2];
+ x2=smps[poshi_l + 3];
+ a = (3.0 * (x0-x1) - xm1 + x2)*0.5;
+ b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5;
+ c = (x1 - xm1)*0.5;
+ outl[i] = (((a * poslo) + b) * poslo + c) * poslo + x0;
+ //right
+ xm1=smps[poshi_r];
+ x0=smps[poshi_r + 1];
+ x1=smps[poshi_r + 2];
+ x2=smps[poshi_r + 3];
+ a = (3.0 * (x0-x1) - xm1 + x2)*0.5;
+ b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5;
+ c = (x1 - xm1)*0.5;
+ outr[i] = (((a * poslo) + b) * poslo + c) * poslo + x0;
+ };
+ return(1);
+};
+
+
+int PADnote::noteout(REALTYPE *outl,REALTYPE *outr){
+ computecurrentparameters();
+ REALTYPE *smps=pars->sample[nsample].smp;
+ if (smps==NULL){
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++){
+ outl[i]=0.0;
+ outr[i]=0.0;
+ };
+ return(1);
+ };
+ REALTYPE smpfreq=pars->sample[nsample].basefreq;
+
+
+ REALTYPE freqrap=realfreq/smpfreq;
+ int freqhi=(int) (floor(freqrap));
+ REALTYPE freqlo=freqrap-floor(freqrap);
+
+
+ if (config.cfg.Interpolation) Compute_Cubic(outl,outr,freqhi,freqlo);
+ else Compute_Linear(outl,outr,freqhi,freqlo);
+
+
+ if (firsttime){
+ fadein(outl);
+ fadein(outr);
+ firsttime=false;
+ };
+
+ NoteGlobalPar.GlobalFilterL->filterout(outl);
+ NoteGlobalPar.GlobalFilterR->filterout(outr);
+
+ //Apply the punch
+ if (NoteGlobalPar.Punch.Enabled!=0){
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++){
+ REALTYPE punchamp=NoteGlobalPar.Punch.initialvalue*NoteGlobalPar.Punch.t+1.0;
+ outl[i]*=punchamp;
+ outr[i]*=punchamp;
+ NoteGlobalPar.Punch.t-=NoteGlobalPar.Punch.dt;
+ if (NoteGlobalPar.Punch.t<0.0) {
+ NoteGlobalPar.Punch.Enabled=0;
+ break;
+ };
+ };
+ };
+
+ if (ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude,globalnewamplitude)){
+ // Amplitude Interpolation
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++){
+ REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(globaloldamplitude,globalnewamplitude,i,SOUND_BUFFER_SIZE);
+ outl[i]*=tmpvol*NoteGlobalPar.Panning;
+ outr[i]*=tmpvol*(1.0-NoteGlobalPar.Panning);
+ };
+ } else {
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
+ outl[i]*=globalnewamplitude*NoteGlobalPar.Panning;
+ outr[i]*=globalnewamplitude*(1.0-NoteGlobalPar.Panning);
+ };
+ };
+
+
+ // Check if the global amplitude is finished.
+ // If it does, disable the note
+ if (NoteGlobalPar.AmpEnvelope->finished()!=0) {
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out
+ REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
+ outl[i]*=tmp;
+ outr[i]*=tmp;
+ };
+ finished_=1;
+ };
+
+ return(1);
+};
+
+int PADnote::finished(){
+ return(finished_);
+};
+
+void PADnote::relasekey(){
+ NoteGlobalPar.FreqEnvelope->relasekey();
+ NoteGlobalPar.FilterEnvelope->relasekey();
+ NoteGlobalPar.AmpEnvelope->relasekey();
+};
+
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/PADnote.h b/muse_qt4_evolution/synti/zynaddsubfx/Synth/PADnote.h
new file mode 100644
index 00000000..2a99577f
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/PADnote.h
@@ -0,0 +1,106 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PADnote.h - The "pad" 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
+*/
+#ifndef PAD_NOTE_H
+#define PAD_NOTE_H
+
+#include "../globals.h"
+#include "../Params/PADnoteParameters.h"
+#include "../Params/Controller.h"
+#include "Envelope.h"
+#include "LFO.h"
+#include "../DSP/Filter.h"
+#include "../Params/Controller.h"
+
+class PADnote{
+ public:
+ PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote);
+ ~PADnote();
+
+ int noteout(REALTYPE *outl,REALTYPE *outr);
+ int finished();
+ void relasekey();
+
+ int ready;
+
+ private:
+ void fadein(REALTYPE *smps);
+ void computecurrentparameters();
+ bool finished_;
+ PADnoteParameters *pars;
+
+ int poshi_l,poshi_r;
+ REALTYPE poslo;
+
+ REALTYPE basefreq;
+ bool firsttime,released;
+
+ int nsample,portamento;
+
+ int Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo);
+ int Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo);
+
+
+ struct{
+ /******************************************
+ * FREQUENCY GLOBAL PARAMETERS *
+ ******************************************/
+ REALTYPE Detune;//cents
+
+ Envelope *FreqEnvelope;
+ LFO *FreqLfo;
+
+ /********************************************
+ * AMPLITUDE GLOBAL PARAMETERS *
+ ********************************************/
+ REALTYPE Volume;// [ 0 .. 1 ]
+
+ REALTYPE Panning;// [ 0 .. 1 ]
+
+ Envelope *AmpEnvelope;
+ LFO *AmpLfo;
+
+ struct {
+ int Enabled;
+ REALTYPE initialvalue,dt,t;
+ } Punch;
+
+ /******************************************
+ * FILTER GLOBAL PARAMETERS *
+ ******************************************/
+ Filter *GlobalFilterL,*GlobalFilterR;
+
+ REALTYPE FilterCenterPitch;//octaves
+ REALTYPE FilterQ;
+ REALTYPE FilterFreqTracking;
+
+ Envelope *FilterEnvelope;
+
+ LFO *FilterLfo;
+ } NoteGlobalPar;
+
+
+ REALTYPE globaloldamplitude,globalnewamplitude,velocity,realfreq;
+ REALTYPE *tmpwave;
+ Controller *ctl;
+};
+
+
+#endif
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/Resonance.C b/muse_qt4_evolution/synti/zynaddsubfx/Synth/Resonance.C
new file mode 100644
index 00000000..fb741055
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/Resonance.C
@@ -0,0 +1,231 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Resonance.C - Resonance
+ 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 <stdlib.h>
+#include "Resonance.h"
+
+
+#include <stdio.h>
+
+Resonance::Resonance():Presets(){
+ setpresettype("Presonance");
+ defaults();
+};
+
+Resonance::~Resonance(){
+};
+
+
+void Resonance::defaults(){
+ Penabled=0;
+ PmaxdB=20;
+ Pcenterfreq=64;//1 kHz
+ Poctavesfreq=64;
+ Pprotectthefundamental=0;
+ ctlcenter=1.0;
+ ctlbw=1.0;
+ for (int i=0;i<N_RES_POINTS;i++) Prespoints[i]=64;
+};
+
+/*
+ * Set a point of resonance function with a value
+ */
+void Resonance::setpoint(int n,unsigned char p){
+ if ((n<0)||(n>=N_RES_POINTS)) return;
+ Prespoints[n]=p;
+};
+
+/*
+ * Apply the resonance to FFT data
+ */
+void Resonance::applyres(int n,FFTFREQS fftdata,REALTYPE freq){
+ if (Penabled==0) return;//if the resonance is disabled
+ REALTYPE sum=0.0,
+ l1=log(getfreqx(0.0)*ctlcenter),
+ l2=log(2.0)*getoctavesfreq()*ctlbw;
+
+ for (int i=0;i<N_RES_POINTS;i++) if (sum<Prespoints[i]) sum=Prespoints[i];
+ if (sum<1.0) sum=1.0;
+
+ for (int i=1;i<n;i++){
+ REALTYPE x=(log(freq*i)-l1)/l2;//compute where the n-th hamonics fits to the graph
+ if (x<0.0) x=0.0;
+
+ x*=N_RES_POINTS;
+ REALTYPE dx=x-floor(x);x=floor(x);
+ int kx1=(int)x; if (kx1>=N_RES_POINTS) kx1=N_RES_POINTS-1;
+ int kx2=kx1+1;if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1;
+ REALTYPE y=(Prespoints[kx1]*(1.0-dx)+Prespoints[kx2]*dx)/127.0-sum/127.0;
+
+ y=pow(10.0,y*PmaxdB/20.0);
+
+ if ((Pprotectthefundamental!=0)&&(i==1)) y=1.0;
+
+ fftdata.c[i]*=y;
+ fftdata.s[i]*=y;
+ };
+};
+
+/*
+ * Gets the response at the frequency "freq"
+ */
+
+REALTYPE Resonance::getfreqresponse(REALTYPE freq){
+ REALTYPE l1=log(getfreqx(0.0)*ctlcenter),
+ l2=log(2.0)*getoctavesfreq()*ctlbw,sum=0.0;
+
+ for (int i=0;i<N_RES_POINTS;i++) if (sum<Prespoints[i]) sum=Prespoints[i];
+ if (sum<1.0) sum=1.0;
+
+ REALTYPE x=(log(freq)-l1)/l2;//compute where the n-th hamonics fits to the graph
+ if (x<0.0) x=0.0;
+ x*=N_RES_POINTS;
+ REALTYPE dx=x-floor(x);x=floor(x);
+ int kx1=(int)x; if (kx1>=N_RES_POINTS) kx1=N_RES_POINTS-1;
+ int kx2=kx1+1;if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1;
+ REALTYPE result=(Prespoints[kx1]*(1.0-dx)+Prespoints[kx2]*dx)/127.0-sum/127.0;
+ result=pow(10.0,result*PmaxdB/20.0);
+ return(result);
+};
+
+
+/*
+ * Smooth the resonance function
+ */
+void Resonance::smooth(){
+ REALTYPE old=Prespoints[0];
+ for (int i=0;i<N_RES_POINTS;i++){
+ old=old*0.4+Prespoints[i]*0.6;
+ Prespoints[i]=(int) old;
+ };
+ old=Prespoints[N_RES_POINTS-1];
+ for (int i=N_RES_POINTS-1;i>0;i--){
+ old=old*0.4+Prespoints[i]*0.6;
+ Prespoints[i]=(int) old+1;
+ if (Prespoints[i]>127) Prespoints[i]=127;
+ };
+};
+
+/*
+ * Randomize the resonance function
+ */
+void Resonance::randomize(int type){
+ int r=(int)(RND*127.0);
+ for (int i=0;i<N_RES_POINTS;i++){
+ Prespoints[i]=r;
+ if ((RND<0.1)&&(type==0)) r=(int)(RND*127.0);
+ if ((RND<0.3)&&(type==1)) r=(int)(RND*127.0);
+ if (type==2) r=(int)(RND*127.0);
+ };
+ smooth();
+};
+
+/*
+ * Interpolate the peaks
+ */
+void Resonance::interpolatepeaks(int type){
+ int x1=0,y1=Prespoints[0];
+ for (int i=1;i<N_RES_POINTS;i++){
+ if ((Prespoints[i]!=64)||(i+1==N_RES_POINTS)){
+ int y2=Prespoints[i];
+ for (int k=0;k<i-x1;k++){
+ float x=(float) k/(i-x1);
+ if (type==0) x=(1-cos(x*PI))*0.5;
+ Prespoints[x1+k]=(int)(y1*(1.0-x)+y2*x);
+ };
+ x1=i;
+ y1=y2;
+ };
+ };
+};
+
+/*
+ * Get the frequency from x, where x is [0..1]; x is the x coordinate
+ */
+REALTYPE Resonance::getfreqx(REALTYPE 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 Resonance::getfreqpos(REALTYPE freq){
+ return((log(freq)-log(getfreqx(0.0)))/log(2.0)/getoctavesfreq());
+};
+
+/*
+ * Get the center frequency of the resonance graph
+ */
+REALTYPE Resonance::getcenterfreq(){
+ return(10000.0*pow(10,-(1.0-Pcenterfreq/127.0)*2.0));
+};
+
+/*
+ * Get the number of octave that the resonance functions applies to
+ */
+REALTYPE Resonance::getoctavesfreq(){
+ return(0.25+10.0*Poctavesfreq/127.0);
+};
+
+void Resonance::sendcontroller(MidiControllers ctl,REALTYPE par){
+ if (ctl==C_resonance_center) ctlcenter=par;
+ else ctlbw=par;
+};
+
+
+
+
+void Resonance::add2XML(XMLwrapper *xml){
+ xml->addparbool("enabled",Penabled);
+
+ if ((Penabled==0)&&(xml->minimal)) return;
+
+ xml->addpar("max_db",PmaxdB);
+ xml->addpar("center_freq",Pcenterfreq);
+ xml->addpar("octaves_freq",Poctavesfreq);
+ xml->addparbool("protect_fundamental_frequency",Pprotectthefundamental);
+ xml->addpar("resonance_points",N_RES_POINTS);
+ for (int i=0;i<N_RES_POINTS;i++){
+ xml->beginbranch("RESPOINT",i);
+ xml->addpar("val",Prespoints[i]);
+ xml->endbranch();
+ };
+};
+
+
+void Resonance::getfromXML(XMLwrapper *xml){
+ Penabled=xml->getparbool("enabled",Penabled);
+
+ PmaxdB=xml->getpar127("max_db",PmaxdB);
+ Pcenterfreq=xml->getpar127("center_freq",Pcenterfreq);
+ Poctavesfreq=xml->getpar127("octaves_freq",Poctavesfreq);
+ Pprotectthefundamental=xml->getparbool("protect_fundamental_frequency",Pprotectthefundamental);
+ for (int i=0;i<N_RES_POINTS;i++){
+ if (xml->enterbranch("RESPOINT",i)==0) continue;
+ Prespoints[i]=xml->getpar127("val",Prespoints[i]);
+ xml->exitbranch();
+ };
+};
+
+
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/Resonance.h b/muse_qt4_evolution/synti/zynaddsubfx/Synth/Resonance.h
new file mode 100644
index 00000000..7b09e295
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/Resonance.h
@@ -0,0 +1,68 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Resonance.h - Resonance
+ 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 RESONANCE_H
+#define RESONANCE_H
+
+#include "../globals.h"
+#include "../Misc/Util.h"
+#include "../Misc/XMLwrapper.h"
+#include "../Params/Presets.h"
+
+#define N_RES_POINTS 256
+
+class Resonance:public Presets{
+ public:
+ Resonance();
+ ~Resonance();
+ void setpoint(int n,unsigned char p);
+ void applyres(int n,FFTFREQS fftdata,REALTYPE freq);
+ void smooth();
+ void interpolatepeaks(int type);
+ void randomize(int type);
+
+ void add2XML(XMLwrapper *xml);
+ void defaults();
+ void getfromXML(XMLwrapper *xml);
+
+
+ REALTYPE getfreqpos(REALTYPE freq);
+ REALTYPE getfreqx(REALTYPE x);
+ REALTYPE getfreqresponse(REALTYPE freq);
+ REALTYPE getcenterfreq();
+ REALTYPE getoctavesfreq();
+ void sendcontroller(MidiControllers ctl,REALTYPE par);
+
+ //parameters
+ unsigned char Penabled; //if the ressonance is enabled
+ unsigned char Prespoints[N_RES_POINTS]; //how many points define the resonance function
+ unsigned char PmaxdB; //how many dB the signal may be amplified
+ unsigned char Pcenterfreq,Poctavesfreq; //the center frequency of the res. func., and the number of octaves
+ unsigned char Pprotectthefundamental; //the fundamental (1-st harmonic) is not damped, even it resonance function is low
+
+ //controllers
+ REALTYPE ctlcenter;//center frequency(relative)
+ REALTYPE ctlbw;//bandwidth(relative)
+
+ private:
+};
+
+#endif
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.C b/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.C
new file mode 100644
index 00000000..f198ba04
--- /dev/null
+++ b/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 <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#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;n<MAX_SUB_HARMONICS;n++){
+ if (pars->Phmag[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;n<numharmonics;n++){
+
+ REALTYPE freq=basefreq*(pos[n]+1);
+
+ //the bandwidth is not absolute(Hz); it is relative to frequency
+ REALTYPE bw=pow(10,(pars->Pbandwidth-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;nph<numstages;nph++){
+ REALTYPE amp=1.0;
+ if (nph==0) amp=gain;
+ initfilter(lfilter[nph+n*numstages],freq,bw,amp,hgain);
+ if (stereo!=0) initfilter(rfilter[nph+n*numstages],freq,bw,amp,hgain);
+ };
+ };
+
+ if (reduceamp<0.001) reduceamp=1.0;
+ volume/=reduceamp;
+
+ oldpitchwheel=0;
+ oldbandwidth=64;
+ if (pars->Pfixedfreq==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;i<SOUND_BUFFER_SIZE;i++){
+ out=smps[i] * filter.b0 + filter.b2 * filter.xn2
+ -filter.a1 * filter.yn1 - filter.a2 * filter.yn2;
+ filter.xn2=filter.xn1;
+ filter.xn1=smps[i];
+ filter.yn2=filter.yn1;
+ filter.yn1=out;
+ smps[i]=out;
+
+ };
+};
+
+/*
+ * Init Parameters
+ */
+void SUBnote::initparameters(REALTYPE freq){
+ AmpEnvelope=new Envelope(pars->AmpEnvelope,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;n<numharmonics;n++){
+ for (int nph=0;nph<numstages;nph++) {
+ if (nph==0) gain=tmpgain;else gain=1.0;
+ computefiltercoefs( lfilter[nph+n*numstages],
+ lfilter[nph+n*numstages].freq*envfreq,
+ lfilter[nph+n*numstages].bw*envbw,gain);
+ };
+ };
+ if (stereo!=0)
+ for (int n=0;n<numharmonics;n++){
+ for (int nph=0;nph<numstages;nph++) {
+ if (nph==0) gain=tmpgain;else gain=1.0;
+ computefiltercoefs( rfilter[nph+n*numstages],
+ rfilter[nph+n*numstages].freq*envfreq,
+ rfilter[nph+n*numstages].bw*envbw,gain);
+ };
+ };
+ oldbandwidth=ctl->bandwidth.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;i<SOUND_BUFFER_SIZE;i++){
+ outl[i]=denormalkillbuf[i];
+ outr[i]=denormalkillbuf[i];
+ };
+
+ if (NoteEnabled==OFF) return(0);
+
+ //left channel
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) tmprnd[i]=RND*2.0-1.0;
+ for (int n=0;n<numharmonics;n++){
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpsmp[i]=tmprnd[i];
+ for (int nph=0;nph<numstages;nph++)
+ filter(lfilter[nph+n*numstages],tmpsmp);
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpsmp[i];
+ };
+
+ if (GlobalFilterL!=NULL) GlobalFilterL->filterout(&outl[0]);
+
+ //right channel
+ if (stereo!=0){
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) tmprnd[i]=RND*2.0-1.0;
+ for (int n=0;n<numharmonics;n++){
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpsmp[i]=tmprnd[i];
+ for (int nph=0;nph<numstages;nph++)
+ filter(rfilter[nph+n*numstages],tmpsmp);
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) outr[i]+=tmpsmp[i];
+ };
+ if (GlobalFilterR!=NULL) GlobalFilterR->filterout(&outr[0]);
+ } else for (i=0;i<SOUND_BUFFER_SIZE;i++) outr[i]=outl[i];
+
+ if (firsttick!=0){
+ int n=10;if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE;
+ for (i=0;i<n;i++) {
+ REALTYPE ampfadein=0.5-0.5*cos((REALTYPE) i/(REALTYPE) n*PI);
+ outl[i]*=ampfadein;
+ outr[i]*=ampfadein;
+ };
+ firsttick=0;
+ };
+
+ if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude,newamplitude)){
+ // Amplitude interpolation
+ for (i=0;i<SOUND_BUFFER_SIZE;i++){
+ REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(oldamplitude
+ ,newamplitude,i,SOUND_BUFFER_SIZE);
+ outl[i]*=tmpvol*panning;
+ outr[i]*=tmpvol*(1.0-panning);
+ };
+ } else {
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {
+ outl[i]*=newamplitude*panning;
+ outr[i]*=newamplitude*(1.0-panning);
+ };
+ };
+
+ oldamplitude=newamplitude;
+ computecurrentparameters();
+
+ // Check if the note needs to be computed more
+ if (AmpEnvelope->finished()!=0){
+ for (i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out
+ REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE;
+ outl[i]*=tmp;
+ outr[i]*=tmp;
+ };
+ KillNote();
+ };
+ return(1);
+};
+
+/*
+ * Relase Key (Note Off)
+ */
+void SUBnote::relasekey(){
+ AmpEnvelope->relasekey();
+ 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);
+};
+
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.h b/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.h
new file mode 100644
index 00000000..6e4e2991
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Synth/SUBnote.h
@@ -0,0 +1,98 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ SUBnote.h - 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
+
+*/
+
+#ifndef SUB_NOTE_H
+#define SUB_NOTE_H
+
+#include "../globals.h"
+#include "../Params/SUBnoteParameters.h"
+#include "../Params/Controller.h"
+#include "Envelope.h"
+#include "../DSP/Filter.h"
+
+class SUBnote{
+ public:
+ SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote);
+ ~SUBnote();
+ int noteout(REALTYPE *outl,REALTYPE *outr);//note output,return 0 if the note is finished
+ void relasekey();
+ int finished();
+
+ int ready; //if I can get the sampledata
+
+ private:
+
+ void computecurrentparameters();
+ void initparameters(REALTYPE freq);
+ void KillNote();
+
+ SUBnoteParameters *pars;
+
+ //parameters
+ int stereo;
+ int numstages;//number of stages of filters
+ int numharmonics;//number of harmonics (after the too higher hamonics are removed)
+ int start;//how the harmonics start
+ REALTYPE basefreq;
+ REALTYPE panning;
+ Envelope *AmpEnvelope;
+ Envelope *FreqEnvelope;
+ Envelope *BandWidthEnvelope;
+
+ Filter *GlobalFilterL,*GlobalFilterR;
+
+ Envelope *GlobalFilterEnvelope;
+
+ //internal values
+ ONOFFTYPE NoteEnabled;
+ int firsttick,portamento;
+ REALTYPE volume,oldamplitude,newamplitude;
+
+ REALTYPE GlobalFilterCenterPitch;//octaves
+ REALTYPE GlobalFilterFreqTracking;
+
+ struct bpfilter{
+ REALTYPE freq,bw,amp; //filter parameters
+ REALTYPE a1,a2,b0,b2;//filter coefs. b1=0
+ REALTYPE xn1,xn2,yn1,yn2; //filter internal values
+ };
+
+ void initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag);
+ void computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain);
+ void filter(bpfilter &filter,REALTYPE *smps);
+
+ bpfilter *lfilter,*rfilter;
+
+ REALTYPE *tmpsmp;
+ REALTYPE *tmprnd;//this is filled with random numbers
+
+ Controller *ctl;
+ int oldpitchwheel,oldbandwidth;
+ REALTYPE globalfiltercenterq;
+
+};
+
+
+
+
+#endif
+