diff options
| -rw-r--r-- | muse/ChangeLog | 8 | ||||
| -rw-r--r-- | muse/synti/deicsonze/TODO | 3 | ||||
| -rw-r--r-- | muse/synti/deicsonze/deicsonze.cpp | 620 | ||||
| -rw-r--r-- | muse/synti/deicsonze/deicsonze.h | 19 | ||||
| -rw-r--r-- | muse/synti/deicsonze/deicsonzegui.cpp | 6 | ||||
| -rw-r--r-- | muse/synti/deicsonze/deicsonzegui.h | 2 | ||||
| -rw-r--r-- | muse/synti/deicsonze/deicsonzegui.ui | 9 | ||||
| -rw-r--r-- | muse/synti/deicsonze/deicsonzepreset.cpp | 2 | ||||
| -rw-r--r-- | muse/synti/deicsonze/deicsonzepreset.h | 2 | 
9 files changed, 380 insertions, 291 deletions
diff --git a/muse/ChangeLog b/muse/ChangeLog index 2ffa972e..3d928e0a 100644 --- a/muse/ChangeLog +++ b/muse/ChangeLog @@ -1,10 +1,12 @@ -24.9  (ng) DeicsOnze 4.0.3 +26.9  (ng) DeicsOnze 0.4.5 +      - add four level of quality +24.9  (ng) DeicsOnze 0.4.3        - add monophony        - finish to clean SutulaBank.dei -23.9  (ng) DeicsOnze 4.0.2 +23.9  (ng) DeicsOnze 0.4.2        - add pitch envelope (but does not sound yet like DeicsOnze's)        - keep cleaning SutulaBank.dei -17.9  (ng) DeicsOnze 4.0.1 +17.9  (ng) DeicsOnze 0.4.1        - add optimization -O3, execution twice faster, but compilation longer        - add portamento        - started to clean SutulaBank.dei diff --git a/muse/synti/deicsonze/TODO b/muse/synti/deicsonze/TODO index d9f0dea4..657af78c 100644 --- a/muse/synti/deicsonze/TODO +++ b/muse/synti/deicsonze/TODO @@ -7,9 +7,8 @@  - Change presetName subcategoryName category with SysEx  - Internal restructure, private vs public, add comment, etc  - getPatchInfo... -- Optimize the code, make 3 level of quality sound +- Optimize the code  - Remember the last directory  - Pan per voices  - Load BUMP preset -- Correct portamento for different samplerates  - calibrate portamento and pitch envelope to fit real DX11 diff --git a/muse/synti/deicsonze/deicsonze.cpp b/muse/synti/deicsonze/deicsonze.cpp index 09f1ab11..9592e120 100644 --- a/muse/synti/deicsonze/deicsonze.cpp +++ b/muse/synti/deicsonze/deicsonze.cpp @@ -2,7 +2,7 @@  //  //    DeicsOnze an emulator of the YAMAHA DX11 synthesizer  // -//    Version 0.4.3 +//    Version 0.4.5  //  //  // @@ -177,6 +177,11 @@ void DeicsOnze::getGeometry(int* x, int* y, int* w, int* h) const {      *h = size.height();  } +void DeicsOnze::setSampleRate(int sr) { +  Mess::setSampleRate(sr); +  setQuality(_global.quality); +} +  //---------------------------------------------------------  //   setGeometry  //--------------------------------------------------------- @@ -516,6 +521,8 @@ inline bool isPitchEnv(PitchEg* pe) {  //---------------------------------------------------------  inline double getPitchEnvCoefInct(int pl) {    /* +    pl = 0 <--> -4oct, pl = 50 <--> 0oct, pl = 100 <--> 4oct +      y = a * exp((pl - 50)/b)      1.0 = a*exp(0) ==> a = 1.0      8.0 = exp(50/b) ==> log 8.0 = 50/b ==> b = 50/log(8.0) @@ -527,13 +534,14 @@ inline double getPitchEnvCoefInct(int pl) {  //---------------------------------------------------------  // getPitchEnvCoefInctInct  //--------------------------------------------------------- -inline double getPitchEnvCoefInctInct(int pl1, int pl2, int pr) { +inline double getPitchEnvCoefInctInct(int pl1, int pl2, int pr, double sr) {    //TODO : depending on the sampleRate    int a = pr; -  double coef = 0.00000025/*COEFPITCHENV*/; -  if(pl1<pl2) return 1.0+coef*((double)(a*a)+1.0); +  double c = 1.0 + COEFPITCHENV*((double)(a*a)+1.0); +  double inctInct = exp(log(c)*48000.0/sr); +  if(pl1<pl2) return(inctInct);    else if(pl1>pl2) -    return 1.0/(1.0+coef*((double)(a*a)+1.0)); +    return(1.0/inctInct);    else return 1.0;  } @@ -725,7 +733,7 @@ void DeicsOnze::setLfo(int c/*channel*/)      //Pitch LFO      _global.channel[c].lfoMaxIndex =        (_global.channel[c].lfoFreq==0?0:(int)((1.0/_global.channel[c].lfoFreq) -				  *(double)sampleRate())); +				  *(double)_global.deiSampleRate));      _global.channel[c].lfoPitch =         (((double)_preset[c]->lfo.pModDepth/(double)MAXPMODDEPTH)         *(COEFPLFO(_preset[c]->sensitivity.pitch))); @@ -766,7 +774,7 @@ void DeicsOnze::setEnvAttack(int c, int v, int k) {      _global.channel[c].voices[v].op[k].envInct=        (_preset[c]->eg[k].ar==0?0:         (double)(RESOLUTION/4)/(envAR2s(_preset[c]->eg[k].ar) -			       *(double)sampleRate())) +			       *_global.deiSampleRate))        *coefAttack(_global.channel[c].attack);  }  void DeicsOnze::setEnvAttack(int c, int k) { @@ -781,7 +789,7 @@ void DeicsOnze::setEnvAttack(int c) {  void DeicsOnze::setEnvRelease(int c, int v, int k) {    if(_global.channel[c].voices[v].op[k].envState==RELEASE)      _global.channel[c].voices[v].op[k].coefVLevel = -      envRR2coef(_preset[c]->eg[k].rr, sampleRate(), +      envRR2coef(_preset[c]->eg[k].rr, _global.deiSampleRate,  		 _global.channel[c].release);  }  void DeicsOnze::setEnvRelease(int c, int k) { @@ -798,13 +806,15 @@ void DeicsOnze::setPitchEnvRelease(int c, int v) {      if(_global.channel[c].voices[v].pitchEnvCoefInct         > _global.channel[c].voices[v].pitchEnvCoefInctPhase1) {        _global.channel[c].voices[v].pitchEnvCoefInctInct =  -	getPitchEnvCoefInctInct(1, 0, _preset[c]->pitchEg.pr3); +	getPitchEnvCoefInctInct(1, 0, _preset[c]->pitchEg.pr3, +				_global.deiSampleRate);        _global.channel[c].voices[v].pitchEnvState = RELEASE_PE;      }      else if(_global.channel[c].voices[v].pitchEnvCoefInct  	    < _global.channel[c].voices[v].pitchEnvCoefInctPhase1) {        _global.channel[c].voices[v].pitchEnvCoefInctInct =  -	getPitchEnvCoefInctInct(0, 1, _preset[c]->pitchEg.pr3); +	getPitchEnvCoefInctInct(0, 1, _preset[c]->pitchEg.pr3, +				_global.deiSampleRate);        _global.channel[c].voices[v].pitchEnvState = RELEASE_PE;      }      else { @@ -813,6 +823,33 @@ void DeicsOnze::setPitchEnvRelease(int c, int v) {      }    }  } + +//----------------------------------------------------------------- +// setQuality +//----------------------------------------------------------------- +void DeicsOnze::setQuality(Quality q) { +  _global.quality = q; +  switch(q) { +  case high : +    _global.qualityCounterTop = 1; +    break; +  case middle : +    _global.qualityCounterTop = 2; +    break; +  case low : +    _global.qualityCounterTop = 4; +    break; +  case ultralow : +    _global.qualityCounterTop = 6; +    break; +  default : printf("Error switch setQuality : out of value\n"); +    break; +  } +  _global.deiSampleRate = (double)sampleRate() +    / (double)_global.qualityCounterTop; +  _global.qualityCounter = 0; +} +  //-----------------------------------------------------------------  // brightness2Amp  //----------------------------------------------------------------- @@ -1250,8 +1287,30 @@ int DeicsOnze::pitchOn2Voice(int c, int pitch) {  //---------------------------------------------------------  // getAttractor  //--------------------------------------------------------- -inline double getAttractor(int portamentoTime) { -  return(1.0 + COEFPORTA/(double)(portamentoTime*portamentoTime)); +inline double getAttractor(int portamentoTime, double sr) { +  /* some explanations + +     c(48000) = c > 1 +      +     f_sr(0) = 1000, f_sr(t) = 2000 +      +     f_sr*2(0) = 1000, f_sr*2(t*2) = 2000 +      +     f_sr(t) = exp(t*ln(c(sr))) * 1000 +      +     2000 = exp(t*ln(c(48000))) * 1000 +      +     2000 = exp(t*2*ln(c(48000*2))) * 1000 +      +     t*ln(c(48000)) = t*2*ln(c(48000*2)) +      +     c(48000*m) = exp(ln(c)/m) +      +     sr = 48000*m +  */ +  double c; +  c = 1.0 + COEFPORTA/(double)(portamentoTime*portamentoTime); +  return(exp(log(c)*48000.0/sr));  }  //--------------------------------------------------------- @@ -1395,7 +1454,7 @@ inline void portamentoUpdate(Channel* p_c, Voice* p_v) {  //---------------------------------------------------------  // pitchEnvelopeUpdate  //--------------------------------------------------------- -inline void pitchEnvelopeUpdate(Voice* v, PitchEg* pe) { +inline void pitchEnvelopeUpdate(Voice* v, PitchEg* pe, double sr) {    if(v->pitchEnvState != OFF_PE) {      switch(v->pitchEnvState) {      case PHASE1 : @@ -1410,7 +1469,7 @@ inline void pitchEnvelopeUpdate(Voice* v, PitchEg* pe) {  	v->pitchEnvState = PHASE2;  	v->pitchEnvCoefInct = getPitchEnvCoefInct(pe->pl2);  	v->pitchEnvCoefInctInct = -	  getPitchEnvCoefInctInct(pe->pl2, pe->pl3, pe->pr2); +	  getPitchEnvCoefInctInct(pe->pl2, pe->pl3, pe->pr2, sr);        }        else v->pitchEnvCoefInct *= v->pitchEnvCoefInctInct;        break; @@ -1489,7 +1548,7 @@ inline double envAR2s(int ar) {  //  return the coefficient for the exponential decrease  //  with respect to d1r and sampleRate, sr  //--------------------------------------------------------- -inline double envD1R2coef(int d1r, int sr) { +inline double envD1R2coef(int d1r, double sr) {    double dt;//such that amp(t+dt)=amp(t)/2    double alpha;//such that amp(t)=exp(alpha*t) @@ -1505,7 +1564,7 @@ inline double envD1R2coef(int d1r, int sr) {        //amp(t+mt)        //following the above equational system we found :        alpha=-log(2)/dt; -      return exp(alpha/(double)sr); +      return exp(alpha/sr);      }  } @@ -1524,7 +1583,7 @@ inline double coefRelease(unsigned char release) {  //  return the coefficient for the exponential decrease  //  with respect to rr and sampleRate, sr  //--------------------------------------------------------- -inline double envRR2coef(int rr, int sr, unsigned char release) { +inline double envRR2coef(int rr, double sr, unsigned char release) {    double dt;//such that amp(t+dt)=amp(t)/2    double alpha;//such that amp(t)=exp(alpha*t) @@ -1539,7 +1598,7 @@ inline double envRR2coef(int rr, int sr, unsigned char release) {    //amp(t+mt)    //following the above equational system we found :    alpha=-log(2)/dt; -  return exp(alpha/(double)sr); +  return exp(alpha/sr);  }  //--------------------------------------------------------- @@ -1558,7 +1617,7 @@ inline double coefAttack(unsigned char attack) {  //   envelope state, making evoluate the envelope  //  sr is the sample rate and st the sine_table  //--------------------------------------------------------- -inline double env2AmpR(int sr, float* wt, Eg eg, OpVoice* p_opVoice) { +inline double env2AmpR(double sr, float* wt, Eg eg, OpVoice* p_opVoice) {    switch(p_opVoice->envState)      {      case ATTACK: @@ -1720,7 +1779,9 @@ void DeicsOnze::readConfiguration(QDomNode qdn) {      //quality      if(qdEl.tagName()==QUALITYSTR) {        _global.quality = (qdEl.text()==HIGHSTR?high: -			 (qdEl.text()==MIDDLESTR?middle:low)); +			 (qdEl.text()==MIDDLESTR?middle: +			  (qdEl.text()==LOWSTR?low:ultralow))); +      setQuality(_global.quality);        unsigned char *dataQuality = new unsigned char[2];        dataQuality[0]=SYSEX_QUALITY;        dataQuality[1]=(unsigned char)_global.quality; @@ -1886,7 +1947,8 @@ void DeicsOnze::writeConfiguration(AL::Xml* xml) {    //xml->strTag(CHANNELNUMSTR, (_global.channelNum==-1?ALLSTR:    //                            str.setNum(_global.channelNum+1)));    xml->strTag(QUALITYSTR, (_global.quality==high?HIGHSTR: -			   (_global.quality==middle?MIDDLESTR:LOWSTR))); +			   (_global.quality==middle?MIDDLESTR: +			    (_global.quality==low?LOWSTR:ULTRALOWSTR))));    xml->intTag(FONTSIZESTR, _global.fontSize);    xml->strTag(SAVECONFIGSTR, (_saveConfig?YESSTRDEI:NOSTRDEI));    xml->strTag(SAVEONLYUSEDSTR, (_saveOnlyUsed?YESSTRDEI:NOSTRDEI));   @@ -2096,6 +2158,7 @@ void DeicsOnze::parseInitData(int length, const unsigned char* data) {        unsigned char dataQuality[2];        dataQuality[0]=SYSEX_QUALITY;        dataQuality[1]=data[NUMQUALITY]; +      setQuality((Quality)data[NUMQUALITY]);        MidiEvent evQuality(0, ME_SYSEX, (const unsigned char*)dataQuality, 2);        _gui->writeEvent(evQuality);        //font size @@ -2249,7 +2312,7 @@ bool DeicsOnze::sysex(int length, const unsigned char* data, bool fromGui) {      //}      //break;    case SYSEX_QUALITY: -    _global.quality = (Quality)data[1]; +    setQuality((Quality)data[1]);      if(!fromGui) {        MidiEvent evSysex(0, ME_SYSEX, data, length);        _gui->writeEvent(evSysex); @@ -2989,7 +3052,8 @@ bool DeicsOnze::playNote(int ch, int pitch, int velo) {  	    if(_preset[ch]->function.portamentoTime!=0) {  	      _global.channel[ch].voices[newVoice].hasAttractor = true;  	      _global.channel[ch].voices[newVoice].attractor = -		getAttractor(_preset[ch]->function.portamentoTime); +		getAttractor(_preset[ch]->function.portamentoTime,  +			     _global.deiSampleRate);  	    }  	    else _global.channel[ch].voices[newVoice].hasAttractor = false;  	    //feedback @@ -3045,7 +3109,8 @@ bool DeicsOnze::playNote(int ch, int pitch, int velo) {  	   (_preset[ch]->function.portamento==FINGER && existsKeyOn(ch))) {  	  _global.channel[ch].voices[newVoice].hasAttractor = true;  	  _global.channel[ch].voices[newVoice].attractor = -	    getAttractor(_preset[ch]->function.portamentoTime); +	    getAttractor(_preset[ch]->function.portamentoTime, +			 _global.deiSampleRate);  	}  	else _global.channel[ch].voices[newVoice].hasAttractor = false; @@ -3069,7 +3134,8 @@ bool DeicsOnze::playNote(int ch, int pitch, int velo) {  	  _global.channel[ch].voices[newVoice].pitchEnvCoefInctInct =  	    getPitchEnvCoefInctInct(_preset[ch]->pitchEg.pl1,  				    _preset[ch]->pitchEg.pl2, -				    _preset[ch]->pitchEg.pr1); +				    _preset[ch]->pitchEg.pr1, +				    _global.deiSampleRate);  	}  	else {  	  _global.channel[ch].voices[newVoice].pitchEnvState = OFF_PE; @@ -3151,7 +3217,7 @@ bool DeicsOnze::playNote(int ch, int pitch, int velo) {  	  //----  	  //compute inct  	  _global.channel[ch].voices[newVoice].op[i].targetInct = -	    (double)RESOLUTION / ( (double)sampleRate() / tempTargetFreq ); +	    (double)RESOLUTION / ( _global.deiSampleRate / tempTargetFreq );  	  if(_global.channel[ch].voices[newVoice].hasAttractor &&  	     !_preset[ch]->frequency[i].isFix)  	    _global.channel[ch].voices[newVoice].op[i].inct = @@ -3217,260 +3283,266 @@ void DeicsOnze::process(float** buffer, int offset, int n) {    float sampleOp[NBROP];    float ampOp[NBROP];    for(int i = 0; i < n; i++) { -    tempLeftOutput = 0.0; -    tempRightOutput = 0.0; -    //per channel -    for(int c = 0; c < NBRCHANNELS; c++) { -      tempChannelOutput = 0.0; -      if(_global.channel[c].isEnable) { -	//lfo, trick : we use the first quater of the wave W2 -	lfoUpdate(_preset[c], &_global.channel[c], waveTable[W2]); - -	//optimization -	tempIncChannel = -	  _global.channel[c].lfoCoefInct * _global.channel[c].pitchBendCoef; - -	//per voice -	for(int j=0; j<_global.channel[c].nbrVoices; j++) { -	  if (_global.channel[c].voices[j].isOn) { -	    //portamento -	    portamentoUpdate(&_global.channel[c], -			     &_global.channel[c].voices[j]); -	    //pitch envelope -	    pitchEnvelopeUpdate(&_global.channel[c].voices[j], -				&_preset[c]->pitchEg); -	    //per op -	    for(int k=0; k<NBROP; k++) { -	      //compute the next index on the wavetable, -	      //without taking account of the feedback and FM modulation -	      _global.channel[c].voices[j].op[k].index= -		plusMod(_global.channel[c].voices[j].op[k].index, -			_global.channel[c].voices[j].op[k].inct -			* tempIncChannel -			* _global.channel[c].voices[j].pitchEnvCoefInct); -	       -	      ampOp[k]=_global.channel[c].voices[j].op[k].amp*COEFLEVEL -		*(_preset[c]->sensitivity.ampOn[k]? -		  _global.channel[c].lfoAmp:1.0) -		*env2AmpR(sampleRate(), waveTable[W2], -			  _preset[c]->eg[k], -			  &_global.channel[c].voices[j].op[k]); -	    } -	    switch(_preset[c]->algorithm) { -	    case FIRST : -	      sampleOp[3]=ampOp[3] -		*waveTable[_preset[c]->oscWave[3]] -		[(int)plusMod(_global.channel[c].voices[j].op[3].index, -			      (float)RESOLUTION -			      *_global.channel[c].voices[j].sampleFeedback)]; -	      sampleOp[2]=ampOp[2] -		*waveTable[_preset[c]->oscWave[2]] -		[(int)plusMod(_global.channel[c].voices[j].op[2].index, -			      (float)RESOLUTION*sampleOp[3])]; -	      sampleOp[1]=ampOp[1] -		*waveTable[_preset[c]->oscWave[1]] -		[(int)plusMod(_global.channel[c].voices[j].op[1].index, -			      (float)RESOLUTION*sampleOp[2])]; -	      sampleOp[0]=ampOp[0] -		*waveTable[_preset[c]->oscWave[0]] -		[(int)plusMod(_global.channel[c].voices[j].op[0].index, -			      (float)RESOLUTION*sampleOp[1])]; -	       -	      sample[j]=sampleOp[0];///COEFLEVEL; -	       -	      _global.channel[c].voices[j].isOn = -		(_global.channel[c].voices[j].op[0].envState!=OFF); -	      break; -	    case SECOND : -	      sampleOp[3]=ampOp[3] -		*waveTable[_preset[c]->oscWave[3]] -		[(int)plusMod(_global.channel[c].voices[j].op[3].index, -			      (float)RESOLUTION -			      *_global.channel[c].voices[j].sampleFeedback)]; -	      sampleOp[2]=ampOp[2] -		*waveTable[_preset[c]->oscWave[2]] -		[(int)_global.channel[c].voices[j].op[2].index]; -	      sampleOp[1]=ampOp[1] -		*waveTable[_preset[c]->oscWave[1]] -		[(int)plusMod(_global.channel[c].voices[j].op[1].index, -			      (float)RESOLUTION -			      *(sampleOp[2]+sampleOp[3])/2.0)]; -	      sampleOp[0]=ampOp[0] -		*waveTable[_preset[c]->oscWave[0]] -		[(int)plusMod(_global.channel[c].voices[j].op[0].index, -			      (float)RESOLUTION -			      *sampleOp[1])]; -	       -	      sample[j]=sampleOp[0];///COEFLEVEL; -	       -	      _global.channel[c].voices[j].isOn = -		(_global.channel[c].voices[j].op[0].envState!=OFF); -	      break; -	    case THIRD : -	      sampleOp[3]=ampOp[3] -		*waveTable[_preset[c]->oscWave[3]] -		[(int)plusMod(_global.channel[c].voices[j].op[3].index, -			      (float)RESOLUTION -			      *_global.channel[c].voices[j].sampleFeedback)]; -	      sampleOp[2]=ampOp[2] -		*waveTable[_preset[c]->oscWave[2]] -		[(int)_global.channel[c].voices[j].op[2].index]; -	      sampleOp[1]=ampOp[1] -		*waveTable[_preset[c]->oscWave[1]] -		[(int)plusMod(_global.channel[c].voices[j].op[1].index, -			      (float)RESOLUTION*sampleOp[2])]; -	      sampleOp[0]=ampOp[0] -		*waveTable[_preset[c]->oscWave[0]] -		[(int)plusMod(_global.channel[c].voices[j].op[0].index, -			      (float)RESOLUTION -			      *(sampleOp[3]+sampleOp[1])/2.0)]; -	       -	      sample[j]=sampleOp[0];///COEFLEVEL; -	       -	      _global.channel[c].voices[j].isOn =  -		(_global.channel[c].voices[j].op[0].envState!=OFF); -	      break; -	    case FOURTH : -	      sampleOp[3]=ampOp[3] -		*waveTable[_preset[c]->oscWave[3]] -		[(int)plusMod(_global.channel[c].voices[j].op[3].index, -			      (float)RESOLUTION -			      *_global.channel[c].voices[j].sampleFeedback)]; -	      sampleOp[2]=ampOp[2] -		*waveTable[_preset[c]->oscWave[2]] -		[(int)plusMod(_global.channel[c].voices[j].op[2].index, -			      (float)RESOLUTION -			      *sampleOp[3])]; -	      sampleOp[1]=ampOp[1] -		*waveTable[_preset[c]->oscWave[1]] -		[(int)_global.channel[c].voices[j].op[1].index]; -	      sampleOp[0]=ampOp[0] -		*waveTable[_preset[c]->oscWave[0]] -		[(int)plusMod(_global.channel[c].voices[j].op[0].index, -			      (float)RESOLUTION -			      *(sampleOp[1]+sampleOp[2])/2.0)]; -	       -	      sample[j]=sampleOp[0];///COEFLEVEL; -	       -	      _global.channel[c].voices[j].isOn = -		(_global.channel[c].voices[j].op[0].envState!=OFF); -	      break; -	    case FIFTH : -	      sampleOp[3]=ampOp[3] -		*waveTable[_preset[c]->oscWave[3]] -		[(int)plusMod(_global.channel[c].voices[j].op[3].index, -			      (float)RESOLUTION -			      *_global.channel[c].voices[j].sampleFeedback)]; -	      sampleOp[2]=ampOp[2] -		*waveTable[_preset[c]->oscWave[2]] -		[(int)plusMod(_global.channel[c].voices[j].op[2].index, -			      (float)RESOLUTION*sampleOp[3])]; -	      sampleOp[1]=ampOp[1] -		*waveTable[_preset[c]->oscWave[1]] -		[(int)_global.channel[c].voices[j].op[1].index]; -	      sampleOp[0]=ampOp[0] -		*waveTable[_preset[c]->oscWave[0]] -		[(int)plusMod(_global.channel[c].voices[j].op[0].index, -			      (float)RESOLUTION*sampleOp[1])]; -	       -	      sample[j]=(sampleOp[0]+sampleOp[2])/2.0;///COEFLEVEL; -	       -	      _global.channel[c].voices[j].isOn =  -		(_global.channel[c].voices[j].op[0].envState!=OFF -		 ||_global.channel[c].voices[j].op[2].envState!=OFF); -	      break; -	    case SIXTH : -	      sampleOp[3]=ampOp[3] -		*waveTable[_preset[c]->oscWave[3]] -		[(int)plusMod(_global.channel[c].voices[j].op[3].index, -			      (float)RESOLUTION -			      *_global.channel[c].voices[j].sampleFeedback)]; -	      sampleOp[2]=ampOp[2] -		*waveTable[_preset[c]->oscWave[2]] -		[(int)plusMod(_global.channel[c].voices[j].op[2].index, -			      (float)RESOLUTION*sampleOp[3])]; -	      sampleOp[1]=ampOp[1] -		*waveTable[_preset[c]->oscWave[1]] -		[(int)plusMod(_global.channel[c].voices[j].op[1].index, -			      (float)RESOLUTION*sampleOp[3])]; -	      sampleOp[0]=ampOp[0] -		*waveTable[_preset[c]->oscWave[0]] -		[(int)plusMod(_global.channel[c].voices[j].op[0].index, -			      (float)RESOLUTION*sampleOp[3])]; -	       -	      sample[j]=(sampleOp[0]+sampleOp[1]+sampleOp[2])/3.0; -	       -	      _global.channel[c].voices[j].isOn =  -		(_global.channel[c].voices[j].op[0].envState!=OFF); -	      break; -	    case SEVENTH : -	      sampleOp[3]=ampOp[3] -		*waveTable[_preset[c]->oscWave[3]] -		[(int)plusMod(_global.channel[c].voices[j].op[3].index, -			      (float)RESOLUTION -			      *_global.channel[c].voices[j].sampleFeedback)]; -	      sampleOp[2]=ampOp[2] -		*waveTable[_preset[c]->oscWave[2]] -		[(int)plusMod(_global.channel[c].voices[j].op[2].index, -			      (float)RESOLUTION*sampleOp[3])]; -	      sampleOp[1]=ampOp[1] -		*waveTable[_preset[c]->oscWave[1]] -		[(int)_global.channel[c].voices[j].op[1].index]; -	      sampleOp[0]=ampOp[0]*waveTable[_preset[c]->oscWave[0]] -		[(int)_global.channel[c].voices[j].op[0].index]; -	       -	      sample[j]=(sampleOp[0]+sampleOp[1]+sampleOp[2])/3.0; +    if(_global.qualityCounter == 0) { +      tempLeftOutput = 0.0; +      tempRightOutput = 0.0; +      //per channel +      for(int c = 0; c < NBRCHANNELS; c++) { +	tempChannelOutput = 0.0; +	if(_global.channel[c].isEnable) { +	  //lfo, trick : we use the first quater of the wave W2 +	  lfoUpdate(_preset[c], &_global.channel[c], waveTable[W2]); +	   +	  //optimization +	  tempIncChannel = +	    _global.channel[c].lfoCoefInct * _global.channel[c].pitchBendCoef; +	   +	  //per voice +	  for(int j=0; j<_global.channel[c].nbrVoices; j++) { +	    if (_global.channel[c].voices[j].isOn) { +	      //portamento +	      portamentoUpdate(&_global.channel[c], +			       &_global.channel[c].voices[j]); +	      //pitch envelope +	      pitchEnvelopeUpdate(&_global.channel[c].voices[j], +				  &_preset[c]->pitchEg, _global.deiSampleRate); +	      //per op +	      for(int k=0; k<NBROP; k++) { +		//compute the next index on the wavetable, +		//without taking account of the feedback and FM modulation +		_global.channel[c].voices[j].op[k].index= +		  plusMod(_global.channel[c].voices[j].op[k].index, +			  _global.channel[c].voices[j].op[k].inct +			  * tempIncChannel +			  * _global.channel[c].voices[j].pitchEnvCoefInct); +		 +		ampOp[k]=_global.channel[c].voices[j].op[k].amp*COEFLEVEL +		  *(_preset[c]->sensitivity.ampOn[k]? +		    _global.channel[c].lfoAmp:1.0) +		  *env2AmpR(_global.deiSampleRate, waveTable[W2], +			    _preset[c]->eg[k], +			    &_global.channel[c].voices[j].op[k]); +	      } +	      switch(_preset[c]->algorithm) { +	      case FIRST : +		sampleOp[3]=ampOp[3] +		  *waveTable[_preset[c]->oscWave[3]] +		  [(int)plusMod(_global.channel[c].voices[j].op[3].index, +				(float)RESOLUTION +				*_global.channel[c].voices[j].sampleFeedback)]; +		sampleOp[2]=ampOp[2] +		  *waveTable[_preset[c]->oscWave[2]] +		  [(int)plusMod(_global.channel[c].voices[j].op[2].index, +				(float)RESOLUTION*sampleOp[3])]; +		sampleOp[1]=ampOp[1] +		  *waveTable[_preset[c]->oscWave[1]] +		  [(int)plusMod(_global.channel[c].voices[j].op[1].index, +				(float)RESOLUTION*sampleOp[2])]; +		sampleOp[0]=ampOp[0] +		  *waveTable[_preset[c]->oscWave[0]] +		  [(int)plusMod(_global.channel[c].voices[j].op[0].index, +				(float)RESOLUTION*sampleOp[1])]; +		 +		sample[j]=sampleOp[0];///COEFLEVEL; +		 +		_global.channel[c].voices[j].isOn = +		  (_global.channel[c].voices[j].op[0].envState!=OFF); +		break; +	      case SECOND : +		sampleOp[3]=ampOp[3] +		  *waveTable[_preset[c]->oscWave[3]] +		  [(int)plusMod(_global.channel[c].voices[j].op[3].index, +				(float)RESOLUTION +				*_global.channel[c].voices[j].sampleFeedback)]; +		sampleOp[2]=ampOp[2] +		  *waveTable[_preset[c]->oscWave[2]] +		  [(int)_global.channel[c].voices[j].op[2].index]; +		sampleOp[1]=ampOp[1] +		  *waveTable[_preset[c]->oscWave[1]] +		  [(int)plusMod(_global.channel[c].voices[j].op[1].index, +				(float)RESOLUTION +				*(sampleOp[2]+sampleOp[3])/2.0)]; +		sampleOp[0]=ampOp[0] +		  *waveTable[_preset[c]->oscWave[0]] +		  [(int)plusMod(_global.channel[c].voices[j].op[0].index, +				(float)RESOLUTION +				*sampleOp[1])]; +		 +		sample[j]=sampleOp[0];///COEFLEVEL; +		 +		_global.channel[c].voices[j].isOn = +		  (_global.channel[c].voices[j].op[0].envState!=OFF); +		break; +	      case THIRD : +		sampleOp[3]=ampOp[3] +		  *waveTable[_preset[c]->oscWave[3]] +		  [(int)plusMod(_global.channel[c].voices[j].op[3].index, +				(float)RESOLUTION +				*_global.channel[c].voices[j].sampleFeedback)]; +		sampleOp[2]=ampOp[2] +		  *waveTable[_preset[c]->oscWave[2]] +		  [(int)_global.channel[c].voices[j].op[2].index]; +		sampleOp[1]=ampOp[1] +		  *waveTable[_preset[c]->oscWave[1]] +		  [(int)plusMod(_global.channel[c].voices[j].op[1].index, +				(float)RESOLUTION*sampleOp[2])]; +		sampleOp[0]=ampOp[0] +		  *waveTable[_preset[c]->oscWave[0]] +		  [(int)plusMod(_global.channel[c].voices[j].op[0].index, +				(float)RESOLUTION +				*(sampleOp[3]+sampleOp[1])/2.0)]; +		 +		sample[j]=sampleOp[0];///COEFLEVEL; +		 +		_global.channel[c].voices[j].isOn =  +		  (_global.channel[c].voices[j].op[0].envState!=OFF); +		break; +	      case FOURTH : +		sampleOp[3]=ampOp[3] +		  *waveTable[_preset[c]->oscWave[3]] +		  [(int)plusMod(_global.channel[c].voices[j].op[3].index, +				(float)RESOLUTION +				*_global.channel[c].voices[j].sampleFeedback)]; +		sampleOp[2]=ampOp[2] +		  *waveTable[_preset[c]->oscWave[2]] +		  [(int)plusMod(_global.channel[c].voices[j].op[2].index, +				(float)RESOLUTION +				*sampleOp[3])]; +		sampleOp[1]=ampOp[1] +		  *waveTable[_preset[c]->oscWave[1]] +		  [(int)_global.channel[c].voices[j].op[1].index]; +		sampleOp[0]=ampOp[0] +		  *waveTable[_preset[c]->oscWave[0]] +		  [(int)plusMod(_global.channel[c].voices[j].op[0].index, +				(float)RESOLUTION +				*(sampleOp[1]+sampleOp[2])/2.0)]; +		 +		sample[j]=sampleOp[0];///COEFLEVEL; +		 +		_global.channel[c].voices[j].isOn = +		  (_global.channel[c].voices[j].op[0].envState!=OFF); +		break; +	      case FIFTH : +		sampleOp[3]=ampOp[3] +		  *waveTable[_preset[c]->oscWave[3]] +		  [(int)plusMod(_global.channel[c].voices[j].op[3].index, +				(float)RESOLUTION +				*_global.channel[c].voices[j].sampleFeedback)]; +		sampleOp[2]=ampOp[2] +		  *waveTable[_preset[c]->oscWave[2]] +		  [(int)plusMod(_global.channel[c].voices[j].op[2].index, +				(float)RESOLUTION*sampleOp[3])]; +		sampleOp[1]=ampOp[1] +		  *waveTable[_preset[c]->oscWave[1]] +		  [(int)_global.channel[c].voices[j].op[1].index]; +		sampleOp[0]=ampOp[0] +		  *waveTable[_preset[c]->oscWave[0]] +		  [(int)plusMod(_global.channel[c].voices[j].op[0].index, +				(float)RESOLUTION*sampleOp[1])]; +		 +		sample[j]=(sampleOp[0]+sampleOp[2])/2.0;///COEFLEVEL; +		 +		_global.channel[c].voices[j].isOn =  +		  (_global.channel[c].voices[j].op[0].envState!=OFF +		   ||_global.channel[c].voices[j].op[2].envState!=OFF); +		break; +	      case SIXTH : +		sampleOp[3]=ampOp[3] +		  *waveTable[_preset[c]->oscWave[3]] +		  [(int)plusMod(_global.channel[c].voices[j].op[3].index, +				(float)RESOLUTION +				*_global.channel[c].voices[j].sampleFeedback)]; +		sampleOp[2]=ampOp[2] +		  *waveTable[_preset[c]->oscWave[2]] +		  [(int)plusMod(_global.channel[c].voices[j].op[2].index, +				(float)RESOLUTION*sampleOp[3])]; +		sampleOp[1]=ampOp[1] +		  *waveTable[_preset[c]->oscWave[1]] +		  [(int)plusMod(_global.channel[c].voices[j].op[1].index, +				(float)RESOLUTION*sampleOp[3])]; +		sampleOp[0]=ampOp[0] +		  *waveTable[_preset[c]->oscWave[0]] +		  [(int)plusMod(_global.channel[c].voices[j].op[0].index, +				(float)RESOLUTION*sampleOp[3])]; +		 +		sample[j]=(sampleOp[0]+sampleOp[1]+sampleOp[2])/3.0; +		 +		_global.channel[c].voices[j].isOn =  +		  (_global.channel[c].voices[j].op[0].envState!=OFF); +		break; +	      case SEVENTH : +		sampleOp[3]=ampOp[3] +		  *waveTable[_preset[c]->oscWave[3]] +		  [(int)plusMod(_global.channel[c].voices[j].op[3].index, +				(float)RESOLUTION +				*_global.channel[c].voices[j].sampleFeedback)]; +		sampleOp[2]=ampOp[2] +		  *waveTable[_preset[c]->oscWave[2]] +		  [(int)plusMod(_global.channel[c].voices[j].op[2].index, +				(float)RESOLUTION*sampleOp[3])]; +		sampleOp[1]=ampOp[1] +		  *waveTable[_preset[c]->oscWave[1]] +		  [(int)_global.channel[c].voices[j].op[1].index]; +		sampleOp[0]=ampOp[0]*waveTable[_preset[c]->oscWave[0]] +		  [(int)_global.channel[c].voices[j].op[0].index]; +		 +		sample[j]=(sampleOp[0]+sampleOp[1]+sampleOp[2])/3.0; +		 +		_global.channel[c].voices[j].isOn = +		  (_global.channel[c].voices[j].op[0].envState!=OFF); +		break;		 +	      case EIGHTH : +		sampleOp[3]=ampOp[3] +		  *waveTable[_preset[c]->oscWave[3]] +		  [(int)plusMod(_global.channel[c].voices[j].op[3].index, +				(float)RESOLUTION +				*_global.channel[c].voices[j].sampleFeedback)]; +		sampleOp[2]=ampOp[2] +		  *waveTable[_preset[c]->oscWave[2]] +		  [(int)_global.channel[c].voices[j].op[2].index]; +		sampleOp[1]=ampOp[1] +		  *waveTable[_preset[c]->oscWave[1]] +		  [(int)_global.channel[c].voices[j].op[1].index]; +		sampleOp[0]=ampOp[0] +		  *waveTable[_preset[c]->oscWave[0]] +		  [(int)_global.channel[c].voices[j].op[0].index]; +		 +		sample[j]= +		  (sampleOp[0]+sampleOp[1]+sampleOp[2]+sampleOp[3]) +		  /4.0; +		 +		_global.channel[c].voices[j].isOn = +		  (_global.channel[c].voices[j].op[0].envState!=OFF +		   || _global.channel[c].voices[j].op[1].envState!=OFF +		   || _global.channel[c].voices[j].op[2].envState!=OFF +		   || _global.channel[c].voices[j].op[3].envState!=OFF); +		break; +	      default : printf("Error : No algorithm"); +		break; +	      } -	      _global.channel[c].voices[j].isOn = -		(_global.channel[c].voices[j].op[0].envState!=OFF); -	      break;		 -	    case EIGHTH : -	      sampleOp[3]=ampOp[3] -		*waveTable[_preset[c]->oscWave[3]] -		[(int)plusMod(_global.channel[c].voices[j].op[3].index, -			      (float)RESOLUTION -			      *_global.channel[c].voices[j].sampleFeedback)]; -	      sampleOp[2]=ampOp[2] -		*waveTable[_preset[c]->oscWave[2]] -		[(int)_global.channel[c].voices[j].op[2].index]; -	      sampleOp[1]=ampOp[1] -		*waveTable[_preset[c]->oscWave[1]] -		[(int)_global.channel[c].voices[j].op[1].index]; -	      sampleOp[0]=ampOp[0] -		*waveTable[_preset[c]->oscWave[0]] -		[(int)_global.channel[c].voices[j].op[0].index]; +	      _global.channel[c].voices[j].volume= +		ampOp[0]+ampOp[1]+ampOp[2]+ampOp[3]; -	      sample[j]= -		(sampleOp[0]+sampleOp[1]+sampleOp[2]+sampleOp[3]) -		/4.0; +	      _global.channel[c].voices[j].sampleFeedback = +		sampleOp[3]*_global.channel[c].feedbackAmp; -	      _global.channel[c].voices[j].isOn = -		(_global.channel[c].voices[j].op[0].envState!=OFF -		 || _global.channel[c].voices[j].op[1].envState!=OFF -		 || _global.channel[c].voices[j].op[2].envState!=OFF -		 || _global.channel[c].voices[j].op[3].envState!=OFF); -	      break; -	    default : printf("Error : No algorithm"); -	      break; +	      tempChannelOutput += sample[j];  	    } -	     -	    _global.channel[c].voices[j].volume= -	      ampOp[0]+ampOp[1]+ampOp[2]+ampOp[3]; -	     -	    _global.channel[c].voices[j].sampleFeedback = -	      sampleOp[3]*_global.channel[c].feedbackAmp; -	     -	    tempChannelOutput += sample[j];  	  } +	  //printf("left out = %f, temp out = %f, left amp = %f\n", +	  //tempLeftOutput, tempChannelOutput, _global.channel[c].ampLeft); +	  tempLeftOutput += tempChannelOutput*_global.channel[c].ampLeft; +	  tempRightOutput += tempChannelOutput*_global.channel[c].ampRight;  	} -	//printf("left out = %f, temp out = %f, left amp = %f\n", -	//tempLeftOutput, tempChannelOutput, _global.channel[c].ampLeft); -	tempLeftOutput += tempChannelOutput*_global.channel[c].ampLeft; -	tempRightOutput += tempChannelOutput*_global.channel[c].ampRight;        } +      _global.lastLeftSample = tempLeftOutput*_global.masterVolume; +      _global.lastRightSample = tempRightOutput*_global.masterVolume;      } -    leftOutput[i] += tempLeftOutput*_global.masterVolume; -    rightOutput[i] += tempRightOutput*_global.masterVolume; +    leftOutput[i] += _global.lastLeftSample; +    rightOutput[i] += _global.lastRightSample; +    _global.qualityCounter++; +    _global.qualityCounter %= _global.qualityCounterTop;    }  } @@ -3491,8 +3563,8 @@ static Mess* instantiate(int sr, QWidget*, const char*)  extern "C" {      static MESS descriptor = {  	"DeicsOnze", -	"DeicsOnze FM DX11 emulator", -	"0.4.3",      // version string +	"DeicsOnze FM DX11/TX81Z emulator", +	"0.4.5",      // version string  	MESS_MAJOR_VERSION, MESS_MINOR_VERSION,  	instantiate      }; diff --git a/muse/synti/deicsonze/deicsonze.h b/muse/synti/deicsonze/deicsonze.h index c16ba969..dd6353b1 100644 --- a/muse/synti/deicsonze/deicsonze.h +++ b/muse/synti/deicsonze/deicsonze.h @@ -2,7 +2,7 @@  //  //    DeicsOnze an emulator of the YAMAHA DX11 synthesizer  // -//    Version 0.4.3 +//    Version 0.4.5  //  //  // @@ -71,7 +71,7 @@  #define COEFERRSUSREL 0.001 //from SUSTAIN or RELEASE until no sound  //#define ERRPORTA 0.001 //dectection to stop portamento  #define COEFPORTA 0.01 //adjusted such that 10 second/octave with max porta -#define COEFPITCHENV 0.000001 //adjust according to a real DX11....??? +#define COEFPITCHENV 0.00000025 //adjust according to a real DX11....???  #define COEFDECAY 1.0  #define COEFSUSTAIN 0.2  #define COEFRELEASE 1.0 @@ -100,6 +100,7 @@  #define HIGHSTR "High"  #define MIDDLESTR "Middle"  #define LOWSTR "Low" +#define ULTRALOWSTR "UltraLow"  #define SYSEX_FONTSIZE 6  #define FONTSIZESTR "fontSize"  #define SYSEX_SAVECONFIG 7 @@ -188,7 +189,7 @@ inline double coefAttack(unsigned char attack);  //  return the coefficient for the exponential decrease  //  with respect to rr and sampleRate, sr  //--------------------------------------------------------- -inline double envRR2coef(int rr, int sr, unsigned char release); +inline double envRR2coef(int rr, double sr, unsigned char release);  //--------------------------------------------------------  // DeicsOnzeCtrl @@ -310,13 +311,19 @@ struct Channel {  enum Quality {    high,    middle, -  low +  low, +  ultralow  };  struct Global {    float masterVolume; -  Quality quality; +  Quality quality; //high, middle, low +  int qualityCounter; //counter to skip some sample depending on quality +  int qualityCounterTop; //number of sample - 1 to skip +  double deiSampleRate; //depending on quality deicsOnze sample rate varies    int fontSize; +  float lastLeftSample; +  float lastRightSample;    Channel channel[NBRCHANNELS];  }; @@ -354,6 +361,7 @@ class DeicsOnze : public Mess {    //preset tree     Set* _set; +  void setSampleRate(int sr);    Preset* findPreset(int hbank, int lbank, int prog);    void initCtrls();    void initGlobal(); @@ -374,6 +382,7 @@ class DeicsOnze : public Mess {    void setEnvRelease(int c, int k); //do the same for all voices of operator k    void setEnvRelease(int c); //do the same for all voices all operators      void setPitchEnvRelease(int c, int v); +  void setQuality(Quality q);    double brightness2Amp(int c, int k); //get the brightness of the operator k    void loadSutulaPresets();    void loadSet(QString s); diff --git a/muse/synti/deicsonze/deicsonzegui.cpp b/muse/synti/deicsonze/deicsonzegui.cpp index ed1b99fd..05855d4b 100644 --- a/muse/synti/deicsonze/deicsonzegui.cpp +++ b/muse/synti/deicsonze/deicsonzegui.cpp @@ -2,7 +2,7 @@  //  //    DeicsOnze an emulator of the YAMAHA DX11 synthesizer  // -//    Version 0.4.3 +//    Version 0.4.5  //  //    deicsonzegui.cpp  // @@ -527,7 +527,9 @@ void DeicsOnzeGui::loadConfiguration() {  void DeicsOnzeGui::setQuality(const QString& q) {    unsigned char* message = new unsigned char[2];    message[0]=SYSEX_QUALITY; -  message[1]=(unsigned char)(q=="High"?high:(q=="Middle"?middle:low)); +  message[1]=(unsigned char)(q=="High"? +			     high:(q=="Middle"? +				   middle:(q=="Low"?low:ultralow)));    sendSysex(message, 2);  }  //----------------------------------------------------------- diff --git a/muse/synti/deicsonze/deicsonzegui.h b/muse/synti/deicsonze/deicsonzegui.h index 57645d60..12accbcf 100644 --- a/muse/synti/deicsonze/deicsonzegui.h +++ b/muse/synti/deicsonze/deicsonzegui.h @@ -2,7 +2,7 @@  //  //    DeicsOnze an emulator of the YAMAHA DX11 synthesizer  // -//    Version 0.4.3 +//    Version 0.4.5  //  //    deicsonzegui.h  // diff --git a/muse/synti/deicsonze/deicsonzegui.ui b/muse/synti/deicsonze/deicsonzegui.ui index a1a55f98..3e3b5bd6 100644 --- a/muse/synti/deicsonze/deicsonzegui.ui +++ b/muse/synti/deicsonze/deicsonzegui.ui @@ -868,7 +868,7 @@            <enum>QFrame::Plain</enum>           </property>           <property name="text" > -          <string>DeicsOnze v0.4.3 Copyright (c) 2004-2006 Nil Geisweiller. Published under GPL licence.</string> +          <string>DeicsOnze v0.4.5 Copyright (c) 2004-2006 Nil Geisweiller. Published under GPL licence.</string>           </property>          </widget>         </item> @@ -5941,7 +5941,7 @@ Wave form 8 = <i>if <b>t</b>&#060 pi then sin(2*<b>t</b>)*sin            <item>             <widget class="QComboBox" name="qualityComboBox" >              <property name="enabled" > -             <bool>false</bool> +             <bool>true</bool>              </property>              <item>               <property name="text" > @@ -5958,6 +5958,11 @@ Wave form 8 = <i>if <b>t</b>&#060 pi then sin(2*<b>t</b>)*sin                <string>Low</string>               </property>              </item> +            <item> +             <property name="text" > +              <string>Ultra low</string> +             </property> +            </item>             </widget>            </item>           </layout> diff --git a/muse/synti/deicsonze/deicsonzepreset.cpp b/muse/synti/deicsonze/deicsonzepreset.cpp index 9b61a1bb..afa43e93 100644 --- a/muse/synti/deicsonze/deicsonzepreset.cpp +++ b/muse/synti/deicsonze/deicsonzepreset.cpp @@ -2,7 +2,7 @@  //  //    DeicsOnze an emulator of the YAMAHA DX11 synthesizer  // -//    Version 0.4.3 +//    Version 0.4.5  //  //    deicsonzepreset.cpp  // diff --git a/muse/synti/deicsonze/deicsonzepreset.h b/muse/synti/deicsonze/deicsonzepreset.h index 290a3e94..6b05939e 100644 --- a/muse/synti/deicsonze/deicsonzepreset.h +++ b/muse/synti/deicsonze/deicsonzepreset.h @@ -2,7 +2,7 @@  //  //    DeicsOnze an emulator of the YAMAHA DX11 synthesizer  // -//    Version 0.4.3 +//    Version 0.4.5  //  //    deicsonzepreset.h  //  | 
