zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 858c0930dacdaa46ff3488920384834c549e8db5
parent 54e859f7d0884ad300c37dbfb366f37b2b312a7e
Author: paulnasca <paulnasca>
Date:   Fri, 10 Nov 2006 16:21:12 +0000

*** empty log message ***

Diffstat:
MChangeLog | 3++-
Msrc/Misc/Part.C | 14+++++++-------
Msrc/Misc/Part.h | 291+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/Synth/ADnote.C | 31+++++++++++++------------------
Msrc/Synth/ADnote.h | 2+-
Msrc/Synth/PADnote.C | 12+++++++-----
Msrc/Synth/PADnote.h | 2+-
Msrc/Synth/SUBnote.C | 21+++++++++++++--------
Msrc/Synth/SUBnote.h | 3++-
9 files changed, 191 insertions(+), 188 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -813,6 +813,7 @@ - Efectele sunt numerotare de la 1 si in la "send to" din partui 01 Nov 2006 - Adaugat patch-urile de Jack Midi si LASH de Lars Luthman 06 Nov 2006 - Aplicat un patch "Fix for ALSA system lockup" de Lars Luthman - +10 Nov 2006 - Aplicat un patch "zyn-extendedmono_v4_update-061110.diff.gz" de Gerald Folcher + diff --git a/src/Misc/Part.C b/src/Misc/Part.C @@ -201,7 +201,7 @@ void Part::NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift){ I'm not sure why though... */ if ((partnote[lastpos].status!=KEY_PLAYING) && (partnote[lastpos].status!=KEY_RELASED_AND_SUSTAINED)){ - ismonofirstnote=true; // No other keys are held or sustained. + ismonofirstnote=true; // No other keys are held or sustained. } } else { // Poly mode is On so just make sure the list is empty. @@ -298,15 +298,15 @@ void Part::NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift){ if (Pkitmode==0){ // "normal mode" legato note if ((kit[0].Padenabled!=0) && (partnote[pos].kititem[0].adnote!=NULL)) - partnote[pos].kititem[0].adnote->ADlegatonote(kit[0].adpars, &ctl, notebasefreq, vel, portamento, note); + partnote[pos].kititem[0].adnote->ADlegatonote(notebasefreq, vel, portamento, note); if ((kit[0].Psubenabled!=0) && (partnote[pos].kititem[0].subnote!=NULL)) - partnote[pos].kititem[0].subnote->SUBlegatonote(kit[0].subpars, &ctl, notebasefreq, vel, portamento, note); + partnote[pos].kititem[0].subnote->SUBlegatonote(notebasefreq, vel, portamento, note); if ((kit[0].Ppadenabled!=0) && (partnote[pos].kititem[0].padnote!=NULL)) - partnote[pos].kititem[0].padnote->PADlegatonote(kit[0].padpars, &ctl, notebasefreq, vel, portamento, note); + partnote[pos].kititem[0].padnote->PADlegatonote(notebasefreq, vel, portamento, note); } else { // "kit mode" legato note int ci=0; @@ -323,15 +323,15 @@ void Part::NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift){ if ((kit[item].Padenabled!=0) && (kit[item].adpars!=NULL) && (partnote[pos].kititem[ci].adnote!=NULL)) - partnote[pos].kititem[ci].adnote->ADlegatonote(kit[item].adpars,&ctl,notebasefreq,vel,portamento,note); + partnote[pos].kititem[ci].adnote->ADlegatonote(notebasefreq,vel,portamento,note); if ((kit[item].Psubenabled!=0) && (kit[item].subpars!=NULL) && (partnote[pos].kititem[ci].subnote!=NULL)) - partnote[pos].kititem[ci].subnote->SUBlegatonote(kit[item].subpars,&ctl,notebasefreq,vel,portamento,note); + partnote[pos].kititem[ci].subnote->SUBlegatonote(notebasefreq,vel,portamento,note); if ((kit[item].Ppadenabled!=0) && (kit[item].padpars!=NULL) && (partnote[pos].kititem[ci].padnote!=NULL)) - partnote[pos].kititem[ci].padnote->PADlegatonote(kit[item].padpars,&ctl,notebasefreq,vel,portamento,note); + partnote[pos].kititem[ci].padnote->PADlegatonote(notebasefreq,vel,portamento,note); /* In the non-legato equivalent, (kit[item].padpars!=NULL) is not checked, is there a reason for that or is it a bug ? */ diff --git a/src/Misc/Part.h b/src/Misc/Part.h @@ -41,153 +41,152 @@ #include <list> // For the monomemnotes list. class Part{ + public: + Part(Microtonal *microtonal_,FFTwrapper *fft_,pthread_mutex_t *mutex_); + ~Part(); - public: - Part(Microtonal *microtonal_,FFTwrapper *fft_,pthread_mutex_t *mutex_); - ~Part(); - - /* Midi commands implemented */ - void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift); - void NoteOff(unsigned char note); - void AllNotesOff();//panic - void SetController(unsigned int type,int par); - void RelaseSustainedKeys();//this is called when the sustain pedal is relased - void RelaseAllKeys();//this is called on AllNotesOff controller - - /* The synthesizer part output */ - void ComputePartSmps();//Part output - - //instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank) - - - //saves the instrument settings to a XML file - //returns 0 for ok or <0 if there is an error - int saveXML(char *filename); - int loadXMLinstrument(const char *filename); - - void add2XML(XMLwrapper *xml); - void add2XMLinstrument(XMLwrapper *xml); - - void defaults(); - void defaultsinstrument(); - - void applyparameters(); - - void getfromXML(XMLwrapper *xml); - void getfromXMLinstrument(XMLwrapper *xml); - - void cleanup(); - -// ADnoteParameters *ADPartParameters; -// SUBnoteParameters *SUBPartParameters; - - //the part's kit - struct { - unsigned char Penabled,Pmuted,Pminkey,Pmaxkey; - unsigned char *Pname; - unsigned char Padenabled,Psubenabled,Ppadenabled; - unsigned char Psendtoparteffect; - ADnoteParameters *adpars; - SUBnoteParameters *subpars; - PADnoteParameters *padpars; - } kit[NUM_KIT_ITEMS]; - - - //Part parameters - void setkeylimit(unsigned char Pkeylimit); - void setkititemstatus(int kititem,int Penabled_); - - unsigned char Penabled;//if the part is enabled - unsigned char Pvolume;//part volume - unsigned char Pminkey;//the minimum key that the part receives noteon messages - unsigned char Pmaxkey;//the maximum key that the part receives noteon messages - void setPvolume(char Pvolume); - unsigned char Pkeyshift;//Part keyshift - unsigned char Prcvchn;//from what midi channel it receive commnads - unsigned char Ppanning;//part panning - void setPpanning(char Ppanning); - unsigned char Pvelsns;//velocity sensing (amplitude velocity scale) - unsigned char Pveloffs;//velocity offset - unsigned char Pnoteon;//if the part receives NoteOn messages - unsigned char Pkitmode;//if the kitmode is enabled - unsigned char Pdrummode;//if all keys are mapped and the system is 12tET (used for drums) - - unsigned char Ppolymode;//Part mode - 0=monophonic , 1=polyphonic - unsigned char Plegatomode;// 0=normal, 1=legato - unsigned char Pkeylimit;//how many keys are alowed to be played same time (0=off), the older will be relased - - unsigned char *Pname; //name of the instrument - struct{//instrument additional information - unsigned char Ptype; - unsigned char Pauthor[MAX_INFO_TEXT_SIZE+1]; - unsigned char Pcomments[MAX_INFO_TEXT_SIZE+1]; - } info; - - - REALTYPE *partoutl;//Left channel output of the part - REALTYPE *partoutr;//Right channel output of the part - - REALTYPE *partfxinputl[NUM_PART_EFX+1],*partfxinputr[NUM_PART_EFX+1];//Left and right signal that pass thru part effects; partfxinput l/r [NUM_PART_EFX] is for "no effect" buffer - - enum NoteStatus{KEY_OFF,KEY_PLAYING,KEY_RELASED_AND_SUSTAINED,KEY_RELASED}; - - REALTYPE volume,oldvolumel,oldvolumer;//this is applied by Master - REALTYPE panning;//this is applied by Master, too - - Controller ctl;//Part controllers - - EffectMgr *partefx[NUM_PART_EFX];//insertion part effects (they are part of the instrument) - unsigned char Pefxroute[NUM_PART_EFX];//how the effect's output is routed(to next effect/to out) - bool Pefxbypass[NUM_PART_EFX];//if the effects are bypassed - - - pthread_mutex_t *mutex; - - int lastnote; - - private: - void KillNotePos(int pos); - void RelaseNotePos(int pos); - void MonoMemRenote(); // MonoMem stuff. - - int killallnotes;//is set to 1 if I want to kill all notes - - struct PartNotes{ - NoteStatus status; - int note;//if there is no note playing, the "note"=-1 - int itemsplaying; - struct { - ADnote *adnote; - SUBnote *subnote; - PADnote *padnote; - int sendtoparteffect; - } kititem[NUM_KIT_ITEMS]; - int time; - }; - - int lastpos; // To keep track of previously used pos. - - // MonoMem stuff - std::list<unsigned char> monomemnotes; // A list to remember held notes. - struct { - unsigned char velocity; - int mkeyshift;// I'm not sure masterkeyshift should be remembered. - } monomem[256]; /* 256 is to cover all possible note values. - monomem[] is used in conjunction with the list to - store the velocity and masterkeyshift values of a - given note (the list only store note values). - For example 'monomem[note].velocity' would be the - velocity value of the note 'note'. - */ - - PartNotes partnote[POLIPHONY]; - - REALTYPE *tmpoutl;//used to get the note - REALTYPE *tmpoutr; - - REALTYPE oldfreq;//this is used for portamento - Microtonal *microtonal; - FFTwrapper *fft; + /* Midi commands implemented */ + void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift); + void NoteOff(unsigned char note); + void AllNotesOff();//panic + void SetController(unsigned int type,int par); + void RelaseSustainedKeys();//this is called when the sustain pedal is relased + void RelaseAllKeys();//this is called on AllNotesOff controller + + /* The synthesizer part output */ + void ComputePartSmps();//Part output + + //instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank) + + + //saves the instrument settings to a XML file + //returns 0 for ok or <0 if there is an error + int saveXML(char *filename); + int loadXMLinstrument(const char *filename); + + void add2XML(XMLwrapper *xml); + void add2XMLinstrument(XMLwrapper *xml); + + void defaults(); + void defaultsinstrument(); + + void applyparameters(); + + void getfromXML(XMLwrapper *xml); + void getfromXMLinstrument(XMLwrapper *xml); + + void cleanup(); + + // ADnoteParameters *ADPartParameters; + // SUBnoteParameters *SUBPartParameters; + + //the part's kit + struct { + unsigned char Penabled,Pmuted,Pminkey,Pmaxkey; + unsigned char *Pname; + unsigned char Padenabled,Psubenabled,Ppadenabled; + unsigned char Psendtoparteffect; + ADnoteParameters *adpars; + SUBnoteParameters *subpars; + PADnoteParameters *padpars; + } kit[NUM_KIT_ITEMS]; + + + //Part parameters + void setkeylimit(unsigned char Pkeylimit); + void setkititemstatus(int kititem,int Penabled_); + + unsigned char Penabled;//if the part is enabled + unsigned char Pvolume;//part volume + unsigned char Pminkey;//the minimum key that the part receives noteon messages + unsigned char Pmaxkey;//the maximum key that the part receives noteon messages + void setPvolume(char Pvolume); + unsigned char Pkeyshift;//Part keyshift + unsigned char Prcvchn;//from what midi channel it receive commnads + unsigned char Ppanning;//part panning + void setPpanning(char Ppanning); + unsigned char Pvelsns;//velocity sensing (amplitude velocity scale) + unsigned char Pveloffs;//velocity offset + unsigned char Pnoteon;//if the part receives NoteOn messages + unsigned char Pkitmode;//if the kitmode is enabled + unsigned char Pdrummode;//if all keys are mapped and the system is 12tET (used for drums) + + unsigned char Ppolymode;//Part mode - 0=monophonic , 1=polyphonic + unsigned char Plegatomode;// 0=normal, 1=legato + unsigned char Pkeylimit;//how many keys are alowed to be played same time (0=off), the older will be relased + + unsigned char *Pname; //name of the instrument + struct{//instrument additional information + unsigned char Ptype; + unsigned char Pauthor[MAX_INFO_TEXT_SIZE+1]; + unsigned char Pcomments[MAX_INFO_TEXT_SIZE+1]; + } info; + + + REALTYPE *partoutl;//Left channel output of the part + REALTYPE *partoutr;//Right channel output of the part + + REALTYPE *partfxinputl[NUM_PART_EFX+1],*partfxinputr[NUM_PART_EFX+1];//Left and right signal that pass thru part effects; partfxinput l/r [NUM_PART_EFX] is for "no effect" buffer + + enum NoteStatus{KEY_OFF,KEY_PLAYING,KEY_RELASED_AND_SUSTAINED,KEY_RELASED}; + + REALTYPE volume,oldvolumel,oldvolumer;//this is applied by Master + REALTYPE panning;//this is applied by Master, too + + Controller ctl;//Part controllers + + EffectMgr *partefx[NUM_PART_EFX];//insertion part effects (they are part of the instrument) + unsigned char Pefxroute[NUM_PART_EFX];//how the effect's output is routed(to next effect/to out) + bool Pefxbypass[NUM_PART_EFX];//if the effects are bypassed + + + pthread_mutex_t *mutex; + + int lastnote; + + private: + void KillNotePos(int pos); + void RelaseNotePos(int pos); + void MonoMemRenote(); // MonoMem stuff. + + int killallnotes;//is set to 1 if I want to kill all notes + + struct PartNotes{ + NoteStatus status; + int note;//if there is no note playing, the "note"=-1 + int itemsplaying; + struct { + ADnote *adnote; + SUBnote *subnote; + PADnote *padnote; + int sendtoparteffect; + } kititem[NUM_KIT_ITEMS]; + int time; + }; + + int lastpos; // To keep track of previously used pos. + + // MonoMem stuff + std::list<unsigned char> monomemnotes; // A list to remember held notes. + struct { + unsigned char velocity; + int mkeyshift;// I'm not sure masterkeyshift should be remembered. + } monomem[256]; /* 256 is to cover all possible note values. + monomem[] is used in conjunction with the list to + store the velocity and masterkeyshift values of a + given note (the list only store note values). + For example 'monomem[note].velocity' would be the + velocity value of the note 'note'. + */ + + PartNotes partnote[POLIPHONY]; + + REALTYPE *tmpoutl;//used to get the note + REALTYPE *tmpoutr; + + REALTYPE oldfreq;//this is used for portamento + Microtonal *microtonal; + FFTwrapper *fft; }; #endif diff --git a/src/Synth/ADnote.C b/src/Synth/ADnote.C @@ -179,11 +179,14 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve }; -// ADlegatonote: This function is a copy of ADnote(...) and +// ADlegatonote: This function is (mostly) a copy of ADnote(...) and // initparameters() stuck together with some lines removed so that it // only alter the already playing note (to perform legato). It is // possible I left stuff that is not required for this. -void ADnote::ADlegatonote(ADnoteParameters *pars, Controller *ctl_, REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_){ +void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_){ + ADnoteParameters *pars=partparams; + //Controller *ctl_=ctl; + portamento=portamento_; midinote=midinote_; basefreq=freq; @@ -191,7 +194,6 @@ void ADnote::ADlegatonote(ADnoteParameters *pars, Controller *ctl_, REALTYPE fre if (velocity>1.0) velocity=1.0; this->velocity=velocity; - stereo=pars->GlobalPar.PStereo; NoteGlobalPar.Detune=getdetune(pars->GlobalPar.PDetuneType ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune); @@ -207,10 +209,8 @@ void ADnote::ADlegatonote(ADnoteParameters *pars, Controller *ctl_, REALTYPE fre for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){ - if (pars->VoicePar[nvoice].Enabled==0) { - NoteVoicePar[nvoice].Enabled=OFF; - continue; //the voice is disabled - }; + if (NoteVoicePar[nvoice].Enabled==OFF) + continue; //(gf) Stay the same as first note in legato. NoteVoicePar[nvoice].fixedfreq=pars->VoicePar[nvoice].Pfixedfreq; NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; @@ -250,14 +250,6 @@ void ADnote::ADlegatonote(ADnoteParameters *pars, Controller *ctl_, REALTYPE fre 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; @@ -316,11 +308,13 @@ void ADnote::ADlegatonote(ADnoteParameters *pars, Controller *ctl_, REALTYPE fre else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0; newamplitude[nvoice]=1.0; - if (partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) { + if ((partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) + && (NoteVoicePar[nvoice].AmpEnvelope!=NULL)){ newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); }; - if (partparams->VoicePar[nvoice].PAmpLfoEnabled!=0){ + if ((partparams->VoicePar[nvoice].PAmpLfoEnabled!=0) + && (NoteVoicePar[nvoice].AmpLfo!=NULL)){ newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); }; @@ -353,7 +347,8 @@ void ADnote::ADlegatonote(ADnoteParameters *pars, Controller *ctl_, REALTYPE fre FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; - if (partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0){ + if ((partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0) + && (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL)){ FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); }; }; diff --git a/src/Synth/ADnote.h b/src/Synth/ADnote.h @@ -42,7 +42,7 @@ class ADnote{ //ADDitive note ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_); ~ADnote(); - void ADlegatonote(ADnoteParameters *pars, Controller *ctl_, REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_); + void ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_); int noteout(REALTYPE *outl,REALTYPE *outr); void relasekey(); diff --git a/src/Synth/PADnote.C b/src/Synth/PADnote.C @@ -126,11 +126,14 @@ PADnote::PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, }; -// PADlegatonote: This function is a copy of PADnote(...) +// PADlegatonote: This function is (mostly) a copy of PADnote(...) // with some lines removed so that it only alter the already playing // note (to perform legato). It is possible I left stuff that is not // required for this. -void PADnote::PADlegatonote(PADnoteParameters *parameters, Controller *ctl_, REALTYPE freq, REALTYPE velocity, int portamento_, int midinote){ +void PADnote::PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote){ + PADnoteParameters *parameters=pars; + //Controller *ctl_=ctl; + portamento=portamento_; this->velocity=velocity; finished_=false; @@ -148,9 +151,8 @@ void PADnote::PADlegatonote(PADnoteParameters *parameters, Controller *ctl_, REA released=false; realfreq=basefreq; - ///NoteGlobalPar.Detune=getdetune(pars->PDetuneType - /// ,pars->PCoarseDetune,pars->PDetune); - getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune);//(gf) modif + + getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); //find out the closest note diff --git a/src/Synth/PADnote.h b/src/Synth/PADnote.h @@ -34,7 +34,7 @@ class PADnote{ PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote); ~PADnote(); - void PADlegatonote(PADnoteParameters *parameters, Controller *ctl_, REALTYPE freq, REALTYPE velocity, int portamento_, int midinote); + void PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote); int noteout(REALTYPE *outl,REALTYPE *outr); int finished(); diff --git a/src/Synth/SUBnote.C b/src/Synth/SUBnote.C @@ -77,6 +77,7 @@ SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,RE if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq pos[numharmonics++]=n; }; + firstnumharmonics=numharmonics;//(gf)Useful in legato mode. if (numharmonics==0) { NoteEnabled=OFF; @@ -142,20 +143,22 @@ SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,RE }; -// SUBlegatonote: This function is a copy of SUBnote(...) and +// SUBlegatonote: This function is (mostly) a copy of SUBnote(...) and // initparameters(...) stuck together with some lines removed so that // it only alter the already playing note (to perform legato). It is // possible I left stuff that is not required for this. -void SUBnote::SUBlegatonote(SUBnoteParameters *parameters, Controller *ctl_, REALTYPE freq, REALTYPE velocity, int portamento_, int midinote){ +void SUBnote::SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote){ + //SUBnoteParameters *parameters=pars; + //Controller *ctl_=ctl; + portamento=portamento_; 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; + + ///start=pars->Pstart; int pos[MAX_SUB_HARMONICS]; @@ -177,13 +180,15 @@ void SUBnote::SUBlegatonote(SUBnoteParameters *parameters, Controller *ctl_, REA (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); - //select only harmonics that desire to compute - numharmonics=0; + + int legatonumharmonics=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; + pos[legatonumharmonics++]=n; }; + if (legatonumharmonics>firstnumharmonics) numharmonics=firstnumharmonics; + else numharmonics=legatonumharmonics; if (numharmonics==0) { NoteEnabled=OFF; diff --git a/src/Synth/SUBnote.h b/src/Synth/SUBnote.h @@ -34,7 +34,7 @@ class SUBnote{ SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote); ~SUBnote(); - void SUBlegatonote(SUBnoteParameters *parameters, Controller *ctl_, REALTYPE freq, REALTYPE velocity, int portamento_, int midinote); + void SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote); int noteout(REALTYPE *outl,REALTYPE *outr);//note output,return 0 if the note is finished void relasekey(); @@ -54,6 +54,7 @@ class SUBnote{ int stereo; int numstages;//number of stages of filters int numharmonics;//number of harmonics (after the too higher hamonics are removed) + int firstnumharmonics;//To keep track of the first note's numharmonics value, useful in legato mode. int start;//how the harmonics start REALTYPE basefreq; REALTYPE panning;