/[svn]/linuxsampler/trunk/src/engines/sfz/SfzSignalUnitRack.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/sfz/SfzSignalUnitRack.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2236 by iliev, Thu Aug 11 18:25:45 2011 UTC revision 3054 by schoenebeck, Thu Dec 15 12:47:45 2016 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2011 Grigor Iliev                                       *   *   Copyright (C) 2011 - 2012 Grigor Iliev                                *
6   *                                                                         *   *                                                                         *
7   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
8   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 21  Line 21 
21   ***************************************************************************/   ***************************************************************************/
22    
23  #include "SfzSignalUnitRack.h"  #include "SfzSignalUnitRack.h"
24  #include "Voice.h"  #include "Engine.h"
25  #include <SF.h>  
26    #define _200TH_ROOT_OF_10 1.011579454259899
27    
28  namespace LinuxSampler { namespace sfz {  namespace LinuxSampler { namespace sfz {
29            
30        double ToRatio(int Centibels) {
31            if (Centibels == 0) return 1.0;
32            return pow(_200TH_ROOT_OF_10, Centibels);
33        }
34        
35      SfzSignalUnit::SfzSignalUnit(SfzSignalUnitRack* rack): SignalUnit(rack), pVoice(rack->pVoice) {      SfzSignalUnit::SfzSignalUnit(SfzSignalUnitRack* rack): SignalUnit(rack), pVoice(rack->pVoice) {
36                    
37      }      }
# Line 59  namespace LinuxSampler { namespace sfz { Line 65  namespace LinuxSampler { namespace sfz {
65      void XFInCCUnit::Calculate() {      void XFInCCUnit::Calculate() {
66          float l = 1;          float l = 1;
67                                    
68          for (int i = 0; i < Ctrls.size(); i++) {          RTList<CC>::Iterator ctrl = pCtrls->first();
69            RTList<CC>::Iterator end  = pCtrls->end();
70            for(; ctrl != end; ++ctrl) {
71              float c = 1;              float c = 1;
72              int influence = Ctrls[i].Influence;              int influence = (*ctrl).Influence;
73              int lo = influence & 0xff;              int lo = influence & 0xff;
74              int hi = influence >> 8;              int hi = influence >> 8;
75              if (Ctrls[i].Value <= lo) {              if ((*ctrl).Value <= lo) {
76                  c = 0;                  c = 0;
77              } else if (Ctrls[i].Value >= hi) {              } else if ((*ctrl).Value >= hi) {
78                  c = 1;                  c = 1;
79              } else {              } else {
80                  float xfVelSize = hi - lo;                  float xfVelSize = hi - lo;
81                  float velPos = Ctrls[i].Value - lo;                  float velPos = (*ctrl).Value - lo;
82                  c = velPos / xfVelSize;                  c = velPos / xfVelSize;
83                  if (pVoice->pRegion->xf_cccurve == ::sfz::POWER) {                  if (pVoice->pRegion->xf_cccurve == ::sfz::POWER) {
84                      c = sin(c * M_PI / 2.0);                      c = sin(c * M_PI / 2.0);
# Line 90  namespace LinuxSampler { namespace sfz { Line 98  namespace LinuxSampler { namespace sfz {
98      void XFOutCCUnit::Calculate() {      void XFOutCCUnit::Calculate() {
99          float l = 1;          float l = 1;
100                                    
101          for (int i = 0; i < Ctrls.size(); i++) {          RTList<CC>::Iterator ctrl = pCtrls->first();
102            RTList<CC>::Iterator end  = pCtrls->end();
103            for(; ctrl != end; ++ctrl) {
104              float c = 1;              float c = 1;
105              int influence = Ctrls[i].Influence;              int influence = (*ctrl).Influence;
106              int lo = influence & 0xff;              int lo = influence & 0xff;
107              int hi = influence >> 8;              int hi = influence >> 8;
108              if (Ctrls[i].Value >= hi) {              if ((*ctrl).Value >= hi) {
109                  c = 0;                  c = 0;
110              } else if (Ctrls[i].Value <= lo) {              } else if ((*ctrl).Value <= lo) {
111                  c = 1;                  c = 1;
112              } else {              } else {
113                  float xfVelSize = hi - lo;                  float xfVelSize = hi - lo;
114                  float velPos = Ctrls[i].Value - lo;                  float velPos = (*ctrl).Value - lo;
115                  c = 1.0f - velPos / xfVelSize;                  c = 1.0f - velPos / xfVelSize;
116                  if (pVoice->pRegion->xf_cccurve == ::sfz::POWER) {                  if (pVoice->pRegion->xf_cccurve == ::sfz::POWER) {
117                      c = sin(c * M_PI / 2.0);                      c = sin(c * M_PI / 2.0);
# Line 119  namespace LinuxSampler { namespace sfz { Line 129  namespace LinuxSampler { namespace sfz {
129            
130            
131      EGv2Unit::EGv2Unit(SfzSignalUnitRack* rack)      EGv2Unit::EGv2Unit(SfzSignalUnitRack* rack)
132          : EGUnit< ::LinuxSampler::sfz::EG>(rack),          : EGUnit< ::LinuxSampler::sfz::EG>(rack), EqUnitSupport(rack), suAmpOnCC(rack), suVolOnCC(rack),
133            suAmpOnCC(rack), suVolOnCC(rack), suPitchOnCC(rack), suCutoffOnCC(rack), suResOnCC(rack)            suPitchOnCC(rack), suCutoffOnCC(rack), suResOnCC(rack), suPanOnCC(rack)
134      { }      { }
135            
136      void EGv2Unit::Trigger() {      void EGv2Unit::Trigger() {
# Line 132  namespace LinuxSampler { namespace sfz { Line 142  namespace LinuxSampler { namespace sfz {
142              f = GetInfluence(egInfo.node[i].time_oncc);              f = GetInfluence(egInfo.node[i].time_oncc);
143              egInfo.node[i].time = std::min(egInfo.node[i].time + f, 100.0f);              egInfo.node[i].time = std::min(egInfo.node[i].time + f, 100.0f);
144          }          }
145          EG.trigger(egInfo, GetSampleRate(), pVoice->MIDIVelocity);          EG.trigger(egInfo, GetSampleRate(), pVoice->MIDIVelocity());
146      }      }
147            
148            
149      void PitchEGUnit::Trigger() {      void PitchEGUnit::Trigger() {
150          ::sfz::Region* const pRegion = pVoice->pRegion;          ::sfz::Region* const pRegion = pVoice->pRegion;
151          depth = pRegion->pitcheg_depth;          depth = pRegion->pitcheg_depth + GetInfluence(pRegion->pitcheg_depth_oncc);
152                    
153          // the length of the decay and release curves are dependent on the velocity          // the length of the decay and release curves are dependent on the velocity
154          const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity);          const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity());
155    
156          // set the delay trigger          // set the delay trigger
157          uiDelayTrigger = (pRegion->pitcheg_delay + pRegion->pitcheg_vel2delay * velrelease) * GetSampleRate();          float delay = pRegion->pitcheg_delay + pRegion->pitcheg_vel2delay * velrelease;
158            delay += GetInfluence(pRegion->pitcheg_delay_oncc);
159            uiDelayTrigger = std::max(0.0f, delay) * GetSampleRate();
160            
161            float start = (pRegion->pitcheg_start + GetInfluence(pRegion->pitcheg_start_oncc)) * 10;
162            
163            float attack = pRegion->pitcheg_attack + pRegion->pitcheg_vel2attack * velrelease;
164            attack = std::max(0.0f, attack + GetInfluence(pRegion->pitcheg_attack_oncc));
165            
166            float hold = pRegion->pitcheg_hold + pRegion->pitcheg_vel2hold * velrelease;
167            hold = std::max(0.0f, hold + GetInfluence(pRegion->pitcheg_hold_oncc));
168            
169            float decay = pRegion->pitcheg_decay + pRegion->pitcheg_vel2decay * velrelease;
170            decay = std::max(0.0f, decay + GetInfluence(pRegion->pitcheg_decay_oncc));
171            
172            float sustain = pRegion->pitcheg_sustain + pRegion->pitcheg_vel2sustain * velrelease;
173            sustain = 10 * (sustain + GetInfluence(pRegion->pitcheg_sustain_oncc));
174            
175            float release = pRegion->pitcheg_release + pRegion->pitcheg_vel2release * velrelease;
176            release = std::max(0.0f, release + GetInfluence(pRegion->pitcheg_release_oncc));
177                    
178          EG.trigger(uint(pRegion->pitcheg_start * 10),          EG.trigger (
179                     std::max(0.0, pRegion->pitcheg_attack + pRegion->pitcheg_vel2attack * velrelease),              uint(std::min(std::max(0.0f, start), 1000.0f)), attack, hold, decay,
180                     std::max(0.0, pRegion->pitcheg_hold + pRegion->pitcheg_vel2hold * velrelease),              uint(std::min(std::max(0.0f, sustain), 1000.0f)), release, GetSampleRate(), true
181                     std::max(0.0, pRegion->pitcheg_decay + pRegion->pitcheg_vel2decay * velrelease),          );
                    uint(std::min(std::max(0.0, 10 * (pRegion->pitcheg_sustain + pRegion->pitcheg_vel2sustain * velrelease)), 1000.0)),  
                    std::max(0.0, pRegion->pitcheg_release + pRegion->pitcheg_vel2release * velrelease),  
                    GetSampleRate());  
182      }      }
183            
184            
185      void FilEGUnit::Trigger() {      void FilEGUnit::Trigger() {
186          ::sfz::Region* const pRegion = pVoice->pRegion;          ::sfz::Region* const pRegion = pVoice->pRegion;
187          depth = pRegion->fileg_depth;          depth = pRegion->fileg_depth + GetInfluence(pRegion->fileg_depth_oncc);
188                    
189          // the length of the decay and release curves are dependent on the velocity          // the length of the decay and release curves are dependent on the velocity
190          const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity);          const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity());
191    
192          // set the delay trigger          // set the delay trigger
193          uiDelayTrigger = (pRegion->fileg_delay + pRegion->fileg_vel2delay * velrelease) * GetSampleRate();          float delay = pRegion->fileg_delay + pRegion->fileg_vel2delay * velrelease;
194            delay += GetInfluence(pRegion->fileg_delay_oncc);
195            uiDelayTrigger = std::max(0.0f, delay) * GetSampleRate();
196            
197            float start = (pRegion->fileg_start + GetInfluence(pRegion->fileg_start_oncc)) * 10;
198            
199            float attack = pRegion->fileg_attack + pRegion->fileg_vel2attack * velrelease;
200            attack = std::max(0.0f, attack + GetInfluence(pRegion->fileg_attack_oncc));
201            
202            float hold = pRegion->fileg_hold + pRegion->fileg_vel2hold * velrelease;
203            hold = std::max(0.0f, hold + GetInfluence(pRegion->fileg_hold_oncc));
204            
205            float decay = pRegion->fileg_decay + pRegion->fileg_vel2decay * velrelease;
206            decay = std::max(0.0f, decay + GetInfluence(pRegion->fileg_decay_oncc));
207            
208            float sustain = pRegion->fileg_sustain + pRegion->fileg_vel2sustain * velrelease;
209            sustain = 10 * (sustain + GetInfluence(pRegion->fileg_sustain_oncc));
210            
211            float release = pRegion->fileg_release + pRegion->fileg_vel2release * velrelease;
212            release = std::max(0.0f, release + GetInfluence(pRegion->fileg_release_oncc));
213                    
214          EG.trigger(uint(pRegion->fileg_start * 10),          EG.trigger (
215                     std::max(0.0, pRegion->fileg_attack + pRegion->fileg_vel2attack * velrelease),              uint(std::min(std::max(0.0f, start), 1000.0f)), attack, hold, decay,
216                     std::max(0.0, pRegion->fileg_hold + pRegion->fileg_vel2hold * velrelease),              uint(std::min(std::max(0.0f, sustain), 1000.0f)), release, GetSampleRate(), true
217                     std::max(0.0, pRegion->fileg_decay + pRegion->fileg_vel2decay * velrelease),          );
                    uint(std::min(std::max(0.0, 10 * (pRegion->fileg_sustain + pRegion->fileg_vel2sustain * velrelease)), 1000.0)),  
                    std::max(0.0, pRegion->fileg_release + pRegion->fileg_vel2release * velrelease),  
                    GetSampleRate());  
218      }      }
219            
220            
# Line 180  namespace LinuxSampler { namespace sfz { Line 222  namespace LinuxSampler { namespace sfz {
222          ::sfz::Region* const pRegion = pVoice->pRegion;          ::sfz::Region* const pRegion = pVoice->pRegion;
223                    
224          // the length of the decay and release curves are dependent on the velocity          // the length of the decay and release curves are dependent on the velocity
225          const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity);          const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity());
226    
227          // set the delay trigger          // set the delay trigger
228          float delay = pRegion->ampeg_delay + pRegion->ampeg_vel2delay * velrelease;          float delay = pRegion->ampeg_delay + pRegion->ampeg_vel2delay * velrelease;
# Line 206  namespace LinuxSampler { namespace sfz { Line 248  namespace LinuxSampler { namespace sfz {
248                    
249          EG.trigger (          EG.trigger (
250              uint(std::min(std::max(0.0f, start), 1000.0f)), attack, hold, decay,              uint(std::min(std::max(0.0f, start), 1000.0f)), attack, hold, decay,
251              uint(std::min(std::max(0.0f, sustain), 1000.0f)), release, GetSampleRate()              uint(std::min(std::max(0.0f, sustain), 1000.0f)), release, GetSampleRate(), false
252          );          );
253      }      }
254            
255            
256      LFOUnit::LFOUnit(SfzSignalUnitRack* rack)      LFOUnit::LFOUnit(SfzSignalUnitRack* rack)
257          : SfzSignalUnit(rack), pLfoInfo(NULL), pLFO(NULL),          : SfzSignalUnit(rack), pLfoInfo(NULL), pLFO(NULL),
258            suFadeEG(rack), suFreqOnCC(rack, this), suDepthOnCC(rack)            suFadeEG(rack), suDepthOnCC(rack), suFreqOnCC(rack, this)
259      { }      { }
260            
261      LFOUnit::LFOUnit(const LFOUnit& Unit)      LFOUnit::LFOUnit(const LFOUnit& Unit)
262          : SfzSignalUnit(Unit), suFadeEG(static_cast<SfzSignalUnitRack*>(Unit.pRack)),          : SfzSignalUnit(Unit), suFadeEG(static_cast<SfzSignalUnitRack*>(Unit.pRack)),
263            suFreqOnCC(static_cast<SfzSignalUnitRack*>(Unit.pRack), this),            suDepthOnCC(static_cast<SfzSignalUnitRack*>(Unit.pRack)),
264            suDepthOnCC(static_cast<SfzSignalUnitRack*>(Unit.pRack))            suFreqOnCC(static_cast<SfzSignalUnitRack*>(Unit.pRack), this)
265      {      {
266          Copy(Unit);          Copy(Unit);
267      }      }
# Line 245  namespace LinuxSampler { namespace sfz { Line 287  namespace LinuxSampler { namespace sfz {
287                            
288              if (f != 0) {              if (f != 0) {
289                  suFadeEG.uiDelayTrigger = pLfoInfo->delay * GetSampleRate();                  suFadeEG.uiDelayTrigger = pLfoInfo->delay * GetSampleRate();
290                  suFadeEG.EG.trigger(0, f, 0, 0, 1000, 0, GetSampleRate());                  suFadeEG.EG.trigger(0, f, 0, 0, 1000, 0, GetSampleRate(), false);
291              }              }
292          }          }
293      }      }
294            
295      void LFOUnit::ValueChanged(CCSignalUnit* pUnit) {      void LFOUnit::ValueChanged(CCSignalUnit* pUnit) {
296            if (pLFO == NULL) return;
297          pLFO->SetFrequency(std::max(0.0f, suFreqOnCC.GetLevel() + pLfoInfo->freq), GetSampleRate());          pLFO->SetFrequency(std::max(0.0f, suFreqOnCC.GetLevel() + pLfoInfo->freq), GetSampleRate());
298      }      }
299            
# Line 268  namespace LinuxSampler { namespace sfz { Line 311  namespace LinuxSampler { namespace sfz {
311            
312            
313      LFOv2Unit::LFOv2Unit(SfzSignalUnitRack* rack)      LFOv2Unit::LFOv2Unit(SfzSignalUnitRack* rack)
314          : LFOUnit(rack), lfos(8), lfo0(1200.0f), lfo1(1200.0f), lfo2(1200.0f),          : LFOUnit(rack), EqUnitSupport(rack), lfos(8), lfo0(1200.0f), lfo1(1200.0f), lfo2(1200.0f),
315            lfo3(1200.0f), lfo4(1200.0f), lfo5(1200.0f), lfo6(1200.0f), lfo7(1200.0f),            lfo3(1200.0f), lfo4(1200.0f), lfo5(1200.0f), lfo6(1200.0f), lfo7(1200.0f),
316            suVolOnCC(rack), suPitchOnCC(rack), suPanOnCC(rack), suCutoffOnCC(rack), suResOnCC(rack)            suVolOnCC(rack), suPitchOnCC(rack), suPanOnCC(rack), suCutoffOnCC(rack), suResOnCC(rack)
317      {      {
# Line 285  namespace LinuxSampler { namespace sfz { Line 328  namespace LinuxSampler { namespace sfz {
328      void LFOv2Unit::Trigger() {      void LFOv2Unit::Trigger() {
329          LFOUnit::Trigger();          LFOUnit::Trigger();
330                    
331          if (pLfoInfo->wave < 0 || pLfoInfo->wave >= lfos.size()) pLFO = &lfo0;          if (/*pLfoInfo->wave < 0 ||*/ pLfoInfo->wave >= lfos.size()) pLFO = &lfo0;
332          else pLFO = lfos[pLfoInfo->wave];          else pLFO = lfos[pLfoInfo->wave];
333                    
334          pLFO->Trigger (          pLFO->Trigger (
# Line 300  namespace LinuxSampler { namespace sfz { Line 343  namespace LinuxSampler { namespace sfz {
343      }      }
344            
345      void AmpLFOUnit::Trigger() {      void AmpLFOUnit::Trigger() {
346            bActive = true;
347          ::sfz::Region* const pRegion = pVoice->pRegion;          ::sfz::Region* const pRegion = pVoice->pRegion;
348          pLfoInfo->delay  = pRegion->amplfo_delay;          pLfoInfo->delay  = pRegion->amplfo_delay + GetInfluence(pRegion->amplfo_delay_oncc);
349          pLfoInfo->freq   = pRegion->amplfo_freq;          pLfoInfo->freq   = pRegion->amplfo_freq;
350          pLfoInfo->fade   = pRegion->amplfo_fade;          pLfoInfo->fade   = pRegion->amplfo_fade + GetInfluence(pRegion->amplfo_fade_oncc);
351          pLfoInfo->volume = pRegion->amplfo_depth;          pLfoInfo->volume = pRegion->amplfo_depth;
352                    
353            if (pLfoInfo->freq <= 0) {
354                if (!pRegion->amplfo_freqcc.empty()) pLfoInfo->freq = 0;
355                else bActive = false;
356            }
357            
358          LFOv1Unit::Trigger();          LFOv1Unit::Trigger();
359      }      }
360            
361      void PitchLFOUnit::Trigger() {      void PitchLFOUnit::Trigger() {
362            bActive = true;
363          ::sfz::Region* const pRegion = pVoice->pRegion;          ::sfz::Region* const pRegion = pVoice->pRegion;
364          pLfoInfo->delay = pRegion->pitchlfo_delay;          pLfoInfo->delay = pRegion->pitchlfo_delay + GetInfluence(pRegion->pitchlfo_delay_oncc);
365          pLfoInfo->freq  = pRegion->pitchlfo_freq;          pLfoInfo->freq  = pRegion->pitchlfo_freq;
366          pLfoInfo->fade  = pRegion->pitchlfo_fade;          pLfoInfo->fade  = pRegion->pitchlfo_fade + GetInfluence(pRegion->pitchlfo_fade_oncc);
367          pLfoInfo->pitch = pRegion->pitchlfo_depth;          pLfoInfo->pitch = pRegion->pitchlfo_depth;
368                    
369            if (pLfoInfo->freq <= 0) {
370                if (!pRegion->pitchlfo_freqcc.empty()) pLfoInfo->freq = 0;
371                else bActive = false;
372            }
373            
374          LFOv1Unit::Trigger();          LFOv1Unit::Trigger();
375      }      }
376            
377      void FilLFOUnit::Trigger() {      void FilLFOUnit::Trigger() {
378            bActive = true;
379          ::sfz::Region* const pRegion = pVoice->pRegion;          ::sfz::Region* const pRegion = pVoice->pRegion;
380          pLfoInfo->delay  = pRegion->fillfo_delay;          pLfoInfo->delay  = pRegion->fillfo_delay + GetInfluence(pRegion->fillfo_delay_oncc);
381          pLfoInfo->freq   = pRegion->fillfo_freq;          pLfoInfo->freq   = pRegion->fillfo_freq;
382          pLfoInfo->fade   = pRegion->fillfo_fade;          pLfoInfo->fade   = pRegion->fillfo_fade + GetInfluence(pRegion->fillfo_fade_oncc);
383          pLfoInfo->cutoff = pRegion->fillfo_depth;          pLfoInfo->cutoff = pRegion->fillfo_depth;
384                    
385            if (pLfoInfo->freq <= 0) {
386                if (!pRegion->fillfo_freqcc.empty()) pLfoInfo->freq = 0;
387                else bActive = false;
388            }
389            
390          LFOv1Unit::Trigger();          LFOv1Unit::Trigger();
391      }      }
392            
# Line 334  namespace LinuxSampler { namespace sfz { Line 395  namespace LinuxSampler { namespace sfz {
395      }      }
396            
397      void CCUnit::Trigger() {      void CCUnit::Trigger() {
398          for (int i = 0; i < Ctrls.size(); i++) {          RTList<CC>::Iterator ctrl = pCtrls->first();
399              Ctrls[i].Value = pVoice->GetControllerValue(Ctrls[i].Controller);          RTList<CC>::Iterator end  = pCtrls->end();
400              if (Ctrls[i].pSmoother != NULL) Ctrls[i].pSmoother->setValue(Ctrls[i].Value);          for(; ctrl != end; ++ctrl) {
401                (*ctrl).Value = pVoice->GetControllerValue((*ctrl).Controller);
402                if ((*ctrl).pSmoother != NULL) {
403                    if ((*ctrl).Step > 0) {
404                        float val = Normalize((*ctrl).Value, (*ctrl).Curve) * (*ctrl).Influence;
405                        (*ctrl).pSmoother->setValue( ((int) (val / (*ctrl).Step)) * (*ctrl).Step );
406                    } else {
407                        (*ctrl).pSmoother->setValue((*ctrl).Value);
408                    }
409                }
410          }          }
411          CCSignalUnit::Trigger();          CCSignalUnit::Trigger();
412      }      }
413            
414       void CCUnit::SetCCs(::sfz::Array<int>& cc) {      void CCUnit::SetCCs(::sfz::Array<int>& cc) {
415           RemoveAllCCs();          RemoveAllCCs();
416           for (int i = 0; i < 128; i++) {          for (int i = 0; i < 128; i++) {
417               if (cc[i] != 0) AddCC(i, cc[i]);              if (cc[i] != 0) AddCC(i, cc[i]);
418           }          }
419       }      }
420            
421       void CCUnit::SetCCs(ArrayList< ::sfz::CC>& cc) {      void CCUnit::SetCCs(::sfz::Array<float>& cc) {
422           RemoveAllCCs();          RemoveAllCCs();
423           for (int i = 0; i < cc.size(); i++) {          for (int i = 0; i < 128; i++) {
424               if (cc[i].Influence != 0) {              if (cc[i] != 0) AddCC(i, cc[i]);
425                   short int curve = cc[i].Curve;          }
426                   if (curve >= GetCurveCount()) curve = -1;      }
427                   AddSmoothCC(cc[i].Controller, cc[i].Influence, curve, cc[i].Smooth);      
428               }      void CCUnit::SetCCs(ArrayList< ::sfz::CC>& cc) {
429           }          RemoveAllCCs();
430       }          for (int i = 0; i < cc.size(); i++) {
431                if (cc[i].Influence != 0) {
432                    short int curve = cc[i].Curve;
433                    if (curve >= GetCurveCount()) curve = -1;
434                    AddSmoothCC(cc[i].Controller, cc[i].Influence, curve, cc[i].Smooth, cc[i].Step);
435                }
436            }
437        }
438            
439       void CCUnit::AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth) {      void CCUnit::AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth, float Step) {
440           AddCC(Controller, Influence, Curve);          AddCC(Controller, Influence, Curve, NULL, Step);
441       }      }
442            
443       int CCUnit::GetCurveCount() {      int CCUnit::GetCurveCount() {
444           return pVoice->pRegion->GetInstrument()->curves.size();          return pVoice->pRegion->GetInstrument()->curves.size();
445       }      }
446            
447       ::sfz::Curve* CCUnit::GetCurve(int idx) {      ::sfz::Curve* CCUnit::GetCurve(int idx) {
448           return &pVoice->pRegion->GetInstrument()->curves[idx];          return &pVoice->pRegion->GetInstrument()->curves[idx];
449       }      }
450            
451       double CCUnit::GetSampleRate() {      double CCUnit::GetSampleRate() {
452          return pVoice->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          return pVoice->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
453      }      }
454        
455        
456        SmoothCCUnit::~SmoothCCUnit() {
457            if (pSmoothers != NULL) delete pSmoothers;
458        }
459            
460       void SmoothCCUnit::AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth) {      void SmoothCCUnit::AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth, float Step) {
461           if (Smooth > 0) {          if (Smooth > 0) {
462               Smoothers[Controller].trigger(Smooth / 1000.0f, GetSampleRate());              if (pSmoothers->poolIsEmpty()) {
463               AddCC(Controller, Influence, Curve, &Smoothers[Controller]);                  std::cerr << "Maximum number of smoothers reached" << std::endl;
464           } else {                  return;
465               AddCC(Controller, Influence, Curve);              }
466           }              Smoother* smoother = &(*(pSmoothers->allocAppend()));
467       }              smoother->trigger(Smooth / 1000.0f, GetSampleRate());
468                AddCC(Controller, Influence, Curve, smoother, Step);
469            } else {
470                AddCC(Controller, Influence, Curve, NULL, Step);
471            }
472        }
473        
474        void SmoothCCUnit::InitSmoothers(Pool<Smoother>* pSmootherPool) {
475            if (pSmoothers != NULL) delete pSmoothers;
476            pSmoothers = new RTList<Smoother>(pSmootherPool);
477        }
478        
479        void SmoothCCUnit::InitCCList(Pool<CC>* pCCPool, Pool<Smoother>* pSmootherPool) {
480            CurveCCUnit::InitCCList(pCCPool, pSmootherPool);
481            InitSmoothers(pSmootherPool);
482        }
483    
484    
485      EndpointUnit::EndpointUnit(SfzSignalUnitRack* rack): EndpointSignalUnit(rack), suXFInCC(rack), suXFOutCC(rack) {      EndpointUnit::EndpointUnit(SfzSignalUnitRack* rack)
486            : EndpointSignalUnit(rack), pitchVeltrackRatio(0), suXFInCC(rack), suXFOutCC(rack), suPanOnCC(rack)
487        {
488                    
489      }      }
490            
491        float EndpointUnit::GetInfluence(::sfz::Array< ::sfz::optional<float> >& cc) {
492            float f = 0;
493            for (int i = 0; i < 128; i++) {
494                if (cc[i]) {
495                    f += (pVoice->GetControllerValue(i) / 127.0f) * (*cc[i]);
496                }
497            }
498            return f;
499        }
500        
501        float EndpointUnit::GetInfluence(::sfz::Array< ::sfz::optional<int> >& cc) {
502            float f = 0;
503            for (int i = 0; i < 128; i++) {
504                if (cc[i]) {
505                    f += (pVoice->GetControllerValue(i) / 127.0f) * (*cc[i]);
506                }
507            }
508            return f;
509        }
510        
511      SfzSignalUnitRack* const EndpointUnit::GetRack() {      SfzSignalUnitRack* const EndpointUnit::GetRack() {
512          return static_cast<SfzSignalUnitRack* const>(pRack);          return static_cast<SfzSignalUnitRack* const>(pRack);
513      }      }
514            
515      void EndpointUnit::Trigger() {      void EndpointUnit::Trigger() {
516            uiDelayTrigger = (uint)GetInfluence(pVoice->pRegion->delay_samples_oncc);
517            if (pVoice->pRegion->delay_samples) uiDelayTrigger += *pVoice->pRegion->delay_samples;
518            
519            if (pVoice->pRegion->delay) {
520                /* here we use the device sample rate */
521                uiDelayTrigger += (uint)( (*pVoice->pRegion->delay) * pVoice->GetSampleRate() );
522            }
523            
524            if (pVoice->pRegion->delay_random) {
525                float r = pVoice->GetEngine()->Random();
526                uiDelayTrigger += (uint)( r * (*pVoice->pRegion->delay_random) * pVoice->GetSampleRate() );
527            }
528            
529            uiDelayTrigger += (uint)(GetInfluence(pVoice->pRegion->delay_oncc) * pVoice->GetSampleRate());
530            
531          float xfInVelCoeff = 1;          float xfInVelCoeff = 1;
532                    
533          if (pVoice->MIDIVelocity <= pVoice->pRegion->xfin_lovel) {          if (pVoice->MIDIVelocity() <= pVoice->pRegion->xfin_lovel) {
534              xfInVelCoeff = 0;              xfInVelCoeff = 0;
535          } else if (pVoice->MIDIVelocity >= pVoice->pRegion->xfin_hivel) {          } else if (pVoice->MIDIVelocity() >= pVoice->pRegion->xfin_hivel) {
536              xfInVelCoeff = 1;              xfInVelCoeff = 1;
537          } else {          } else {
538              float xfVelSize = pVoice->pRegion->xfin_hivel - pVoice->pRegion->xfin_lovel;              float xfVelSize = pVoice->pRegion->xfin_hivel - pVoice->pRegion->xfin_lovel;
539              float velPos = pVoice->MIDIVelocity - pVoice->pRegion->xfin_lovel;              float velPos = pVoice->MIDIVelocity() - pVoice->pRegion->xfin_lovel;
540              xfInVelCoeff = velPos / xfVelSize;              xfInVelCoeff = velPos / xfVelSize;
541              if (pVoice->pRegion->xf_velcurve == ::sfz::POWER) {              if (pVoice->pRegion->xf_velcurve == ::sfz::POWER) {
542                  xfInVelCoeff = sin(xfInVelCoeff * M_PI / 2.0);                  xfInVelCoeff = sin(xfInVelCoeff * M_PI / 2.0);
# Line 411  namespace LinuxSampler { namespace sfz { Line 545  namespace LinuxSampler { namespace sfz {
545                    
546          float xfOutVelCoeff = 1;          float xfOutVelCoeff = 1;
547                    
548          if (pVoice->MIDIVelocity >= pVoice->pRegion->xfout_hivel) {          if (pVoice->MIDIVelocity() >= pVoice->pRegion->xfout_hivel) {
549              if (pVoice->pRegion->xfout_lovel < 127 /* is set */) xfOutVelCoeff = 0;              if (pVoice->pRegion->xfout_lovel < 127 /* is set */) xfOutVelCoeff = 0;
550          } else if (pVoice->MIDIVelocity <= pVoice->pRegion->xfout_lovel) {          } else if (pVoice->MIDIVelocity() <= pVoice->pRegion->xfout_lovel) {
551              xfOutVelCoeff = 1;              xfOutVelCoeff = 1;
552          } else {          } else {
553              float xfVelSize = pVoice->pRegion->xfout_hivel - pVoice->pRegion->xfout_lovel;              float xfVelSize = pVoice->pRegion->xfout_hivel - pVoice->pRegion->xfout_lovel;
554              float velPos = pVoice->MIDIVelocity - pVoice->pRegion->xfout_lovel;              float velPos = pVoice->MIDIVelocity() - pVoice->pRegion->xfout_lovel;
555              xfOutVelCoeff = 1.0f - velPos / xfVelSize;              xfOutVelCoeff = 1.0f - velPos / xfVelSize;
556              if (pVoice->pRegion->xf_velcurve == ::sfz::POWER) {              if (pVoice->pRegion->xf_velcurve == ::sfz::POWER) {
557                  xfOutVelCoeff = sin(xfOutVelCoeff * M_PI / 2.0);                  xfOutVelCoeff = sin(xfOutVelCoeff * M_PI / 2.0);
# Line 426  namespace LinuxSampler { namespace sfz { Line 560  namespace LinuxSampler { namespace sfz {
560                    
561          float xfInKeyCoeff = 1;          float xfInKeyCoeff = 1;
562                    
563          if (pVoice->MIDIKey <= pVoice->pRegion->xfin_lokey) {          if (pVoice->MIDIKey() <= pVoice->pRegion->xfin_lokey) {
564              if (pVoice->pRegion->xfin_hikey > 0 /* is set */) xfInKeyCoeff = 0;              if (pVoice->pRegion->xfin_hikey > 0 /* is set */) xfInKeyCoeff = 0;
565          } else if (pVoice->MIDIKey >= pVoice->pRegion->xfin_hikey) {          } else if (pVoice->MIDIKey() >= pVoice->pRegion->xfin_hikey) {
566              xfInKeyCoeff = 1;              xfInKeyCoeff = 1;
567          } else {          } else {
568              float xfKeySize = pVoice->pRegion->xfin_hikey - pVoice->pRegion->xfin_lokey;              float xfKeySize = pVoice->pRegion->xfin_hikey - pVoice->pRegion->xfin_lokey;
569              float keyPos = pVoice->MIDIKey - pVoice->pRegion->xfin_lokey;              float keyPos = pVoice->MIDIKey() - pVoice->pRegion->xfin_lokey;
570              xfInKeyCoeff = keyPos / xfKeySize;              xfInKeyCoeff = keyPos / xfKeySize;
571              if (pVoice->pRegion->xf_keycurve == ::sfz::POWER) {              if (pVoice->pRegion->xf_keycurve == ::sfz::POWER) {
572                  xfInKeyCoeff = sin(xfInKeyCoeff * M_PI / 2.0);                  xfInKeyCoeff = sin(xfInKeyCoeff * M_PI / 2.0);
# Line 441  namespace LinuxSampler { namespace sfz { Line 575  namespace LinuxSampler { namespace sfz {
575                    
576          float xfOutKeyCoeff = 1;          float xfOutKeyCoeff = 1;
577                    
578          if (pVoice->MIDIKey >= pVoice->pRegion->xfout_hikey) {          if (pVoice->MIDIKey() >= pVoice->pRegion->xfout_hikey) {
579              if (pVoice->pRegion->xfout_lokey < 127 /* is set */) xfOutKeyCoeff = 0;              if (pVoice->pRegion->xfout_lokey < 127 /* is set */) xfOutKeyCoeff = 0;
580          } else if (pVoice->MIDIKey <= pVoice->pRegion->xfout_lokey) {          } else if (pVoice->MIDIKey() <= pVoice->pRegion->xfout_lokey) {
581              xfOutKeyCoeff = 1;              xfOutKeyCoeff = 1;
582          } else {          } else {
583              float xfKeySize = pVoice->pRegion->xfout_hikey - pVoice->pRegion->xfout_lokey;              float xfKeySize = pVoice->pRegion->xfout_hikey - pVoice->pRegion->xfout_lokey;
584              float keyPos = pVoice->MIDIKey - pVoice->pRegion->xfout_lokey;              float keyPos = pVoice->MIDIKey() - pVoice->pRegion->xfout_lokey;
585              xfOutKeyCoeff = 1.0f - keyPos / xfKeySize;              xfOutKeyCoeff = 1.0f - keyPos / xfKeySize;
586              if (pVoice->pRegion->xf_keycurve == ::sfz::POWER) {              if (pVoice->pRegion->xf_keycurve == ::sfz::POWER) {
587                  xfOutKeyCoeff = sin(xfOutKeyCoeff * M_PI / 2.0);                  xfOutKeyCoeff = sin(xfOutKeyCoeff * M_PI / 2.0);
# Line 458  namespace LinuxSampler { namespace sfz { Line 592  namespace LinuxSampler { namespace sfz {
592                    
593          suXFInCC.SetCrossFadeCCs(pVoice->pRegion->xfin_locc, pVoice->pRegion->xfin_hicc);          suXFInCC.SetCrossFadeCCs(pVoice->pRegion->xfin_locc, pVoice->pRegion->xfin_hicc);
594          suXFOutCC.SetCrossFadeCCs(pVoice->pRegion->xfout_locc, pVoice->pRegion->xfout_hicc);          suXFOutCC.SetCrossFadeCCs(pVoice->pRegion->xfout_locc, pVoice->pRegion->xfout_hicc);
595            
596            suPanOnCC.SetCCs(pVoice->pRegion->pan_oncc);
597            
598            pitchVeltrackRatio = RTMath::CentsToFreqRatioUnlimited((pVoice->MIDIVelocity() / 127.0f) * pVoice->pRegion->pitch_veltrack);
599      }      }
600            
601      bool EndpointUnit::Active() {      bool EndpointUnit::Active() {
602            if (pRack->isReleaseStageEntered() && uiDelayTrigger) {
603                return false; // The key was released before the delay end, so the voice won't play at all.
604            }
605            
606          if (GetRack()->suVolEG.Active()) return true;          if (GetRack()->suVolEG.Active()) return true;
607                    
608          bool b = false;          bool b = false;
# Line 487  namespace LinuxSampler { namespace sfz { Line 629  namespace LinuxSampler { namespace sfz {
629                            
630              if (dB >= -144) {              if (dB >= -144) {
631                  if (amp == 0 && eg->suAmpOnCC.GetCCCount() == 0) amp = 1.0f;                  if (amp == 0 && eg->suAmpOnCC.GetCCCount() == 0) amp = 1.0f;
632                  amp *= ::sf2::ToRatio(dB * 10.0);                  amp *= ToRatio(dB * 10.0);
633              }              }
634                            
635              vol += amp * eg->GetLevel();              vol += amp * eg->GetLevel();
# Line 496  namespace LinuxSampler { namespace sfz { Line 638  namespace LinuxSampler { namespace sfz {
638          AmpLFOUnit* u = &(GetRack()->suAmpLFO);          AmpLFOUnit* u = &(GetRack()->suAmpLFO);
639          CCSignalUnit* u2 = &(GetRack()->suAmpLFO.suDepthOnCC);          CCSignalUnit* u2 = &(GetRack()->suAmpLFO.suDepthOnCC);
640          float f = u2->Active() ? u2->GetLevel() : 0;          float f = u2->Active() ? u2->GetLevel() : 0;
641          vol *= u->Active() ? ::sf2::ToRatio((u->GetLevel() * (u->pLfoInfo->volume + f) * 10.0)) : 1;          vol *= u->Active() ? ToRatio((u->GetLevel() * (u->pLfoInfo->volume + f) * 10.0)) : 1;
642                    
643          vol *= ::sf2::ToRatio(GetRack()->suVolOnCC.GetLevel() * 10.0);          vol *= ToRatio(GetRack()->suVolOnCC.GetLevel() * 10.0);
644                    
645          for (int i = 0; i < GetRack()->volLFOs.size(); i++) {          for (int i = 0; i < GetRack()->volLFOs.size(); i++) {
646              LFOv2Unit* lfo = GetRack()->volLFOs[i];              LFOv2Unit* lfo = GetRack()->volLFOs[i];
647              if (!lfo->Active()) continue;              if (!lfo->Active()) continue;
648                            
649              float f = lfo->suVolOnCC.Active() ? lfo->suVolOnCC.GetLevel() : 0;              float f = lfo->suVolOnCC.Active() ? lfo->suVolOnCC.GetLevel() : 0;
650              vol *= ::sf2::ToRatio(lfo->GetLevel() * (lfo->pLfoInfo->volume + f) * 10.0);              vol *= ToRatio(lfo->GetLevel() * (lfo->pLfoInfo->volume + f) * 10.0);
651          }          }
652                    
653          if (suXFInCC.Active())  vol *= suXFInCC.GetLevel();          if (suXFInCC.Active())  vol *= suXFInCC.GetLevel();
# Line 514  namespace LinuxSampler { namespace sfz { Line 656  namespace LinuxSampler { namespace sfz {
656      }      }
657            
658      float EndpointUnit::GetFilterCutoff() {      float EndpointUnit::GetFilterCutoff() {
659          float val;          float val = GetRack()->suCutoffOnCC.Active() ? RTMath::CentsToFreqRatioUnlimited(GetRack()->suCutoffOnCC.GetLevel()) : 1;
660                    
661          FilLFOUnit* u = &(GetRack()->suFilLFO);          FilLFOUnit* u = &(GetRack()->suFilLFO);
662          CCSignalUnit* u1 = &(GetRack()->suFilLFO.suDepthOnCC);          CCSignalUnit* u1 = &(GetRack()->suFilLFO.suDepthOnCC);
663          float f = u1->Active() ? u1->GetLevel() : 0;          float f = u1->Active() ? u1->GetLevel() : 0;
664          val = u->Active() ? RTMath::CentsToFreqRatioUnlimited(u->GetLevel() * (u->pLfoInfo->cutoff + f)) : 1;          val *= u->Active() ? RTMath::CentsToFreqRatioUnlimited(u->GetLevel() * (u->pLfoInfo->cutoff + f)) : 1;
665                    
666          FilEGUnit* u2 = &(GetRack()->suFilEG);          FilEGUnit* u2 = &(GetRack()->suFilEG);
667          val *= u2->Active() ? RTMath::CentsToFreqRatioUnlimited(u2->GetLevel() * u2->depth) : 1;          val *= u2->Active() ? RTMath::CentsToFreqRatioUnlimited(u2->GetLevel() * u2->depth) : 1;
# Line 546  namespace LinuxSampler { namespace sfz { Line 688  namespace LinuxSampler { namespace sfz {
688      }      }
689            
690      float EndpointUnit::CalculateFilterCutoff(float cutoff) {      float EndpointUnit::CalculateFilterCutoff(float cutoff) {
691           cutoff *= GetFilterCutoff();          cutoff *= GetFilterCutoff();
692           float maxCutoff = 0.49 * pVoice->GetSampleRate();          float maxCutoff = 0.49 * pVoice->GetSampleRate();
693           return cutoff > maxCutoff ? maxCutoff : cutoff;          return cutoff > maxCutoff ? maxCutoff : cutoff;
694      }      }
695            
696      float EndpointUnit::GetPitch() {      float EndpointUnit::GetPitch() {
697          double p;          double p = GetRack()->suPitchOnCC.Active() ? RTMath::CentsToFreqRatioUnlimited(GetRack()->suPitchOnCC.GetLevel()) : 1;
698            
699          EGv1Unit* u = &(GetRack()->suPitchEG);          EGv1Unit* u = &(GetRack()->suPitchEG);
700          p = u->Active() ? RTMath::CentsToFreqRatioUnlimited(u->GetLevel() * u->depth) : 1;          p *= u->Active() ? RTMath::CentsToFreqRatioUnlimited(u->GetLevel() * u->depth) : 1;
701                    
702          for (int i = 0; i < GetRack()->pitchEGs.size(); i++) {          for (int i = 0; i < GetRack()->pitchEGs.size(); i++) {
703              EGv2Unit* eg = GetRack()->pitchEGs[i];              EGv2Unit* eg = GetRack()->pitchEGs[i];
# Line 577  namespace LinuxSampler { namespace sfz { Line 720  namespace LinuxSampler { namespace sfz {
720              p *= RTMath::CentsToFreqRatioUnlimited(lfo->GetLevel() * (lfo->pLfoInfo->pitch + f));              p *= RTMath::CentsToFreqRatioUnlimited(lfo->GetLevel() * (lfo->pLfoInfo->pitch + f));
721          }          }
722                    
723          return p;          return p * pitchVeltrackRatio;
724      }      }
725            
726      float EndpointUnit::GetResonance() {      float EndpointUnit::GetResonance() {
727           float val = 0;           float val = GetRack()->suResOnCC.Active() ? GetRack()->suResOnCC.GetLevel() : 0;
728                    
729          for (int i = 0; i < GetRack()->resEGs.size(); i++) {          for (int i = 0; i < GetRack()->resEGs.size(); i++) {
730              EGv2Unit* eg = GetRack()->resEGs[i];              EGv2Unit* eg = GetRack()->resEGs[i];
# Line 603  namespace LinuxSampler { namespace sfz { Line 746  namespace LinuxSampler { namespace sfz {
746      }      }
747            
748      float EndpointUnit::GetPan() {      float EndpointUnit::GetPan() {
749          float pan = 0;          float pan = suPanOnCC.Active() ? suPanOnCC.GetLevel() : 0;
750            
751            for (int i = 0; i < GetRack()->panEGs.size(); i++) {
752                EGv2Unit* eg = GetRack()->panEGs[i];
753                if (!eg->Active()) continue;
754                
755                float f = eg->suPanOnCC.Active() ? eg->suPanOnCC.GetLevel() : 0;
756                
757                if (eg->pEGInfo->pan_curve >= 0 && eg->pEGInfo->pan_curve < suPanOnCC.GetCurveCount()) {
758                    uint8_t val = eg->GetLevel() * 127;
759                    if (val > 127) val = 127;
760                    pan += eg->pEGInfo->pan * suPanOnCC.GetCurve(eg->pEGInfo->pan_curve)->v[val] +  eg->GetLevel() * f;
761                } else {
762                    pan += eg->GetLevel() * (eg->pEGInfo->pan + f);
763                }
764            }
765                    
766          for (int i = 0; i < GetRack()->panLFOs.size(); i++) {          for (int i = 0; i < GetRack()->panLFOs.size(); i++) {
767              LFOv2Unit* lfo = GetRack()->panLFOs[i];              LFOv2Unit* lfo = GetRack()->panLFOs[i];
# Line 613  namespace LinuxSampler { namespace sfz { Line 771  namespace LinuxSampler { namespace sfz {
771              pan += lfo->GetLevel() * (lfo->pLfoInfo->pan + f);              pan += lfo->GetLevel() * (lfo->pLfoInfo->pan + f);
772          }          }
773                    
         if(pan < -100) return -100;  
         if(pan >  100) return  100;  
           
774          return pan;          return pan;
775      }      }
776            
777            
778      SfzSignalUnitRack::SfzSignalUnitRack(Voice* voice)      SfzSignalUnitRack::SfzSignalUnitRack(Voice* voice)
779          : SignalUnitRack(MaxUnitCount), pVoice(voice), suEndpoint(this), suVolEG(this), suFilEG(this), suPitchEG(this),          : SignalUnitRack(MaxUnitCount), EqUnitSupport(this, voice),
780          EGs(maxEgCount), volEGs(maxEgCount), pitchEGs(maxEgCount), filEGs(maxEgCount), resEGs(maxEgCount), suVolOnCC(this),          suEndpoint(this), suVolEG(this), suFilEG(this), suPitchEG(this),
781          suAmpLFO(this), suPitchLFO(this), suFilLFO(this),          suAmpLFO(this), suPitchLFO(this), suFilLFO(this),
782            suVolOnCC(this), suPitchOnCC(this), suCutoffOnCC(this), suResOnCC(this),
783            EGs(maxEgCount), volEGs(maxEgCount), pitchEGs(maxEgCount), filEGs(maxEgCount),
784            resEGs(maxEgCount), panEGs(maxEgCount), eqEGs(maxEgCount),
785          LFOs(maxLfoCount), volLFOs(maxLfoCount), pitchLFOs(maxLfoCount),          LFOs(maxLfoCount), volLFOs(maxLfoCount), pitchLFOs(maxLfoCount),
786          filLFOs(maxLfoCount), resLFOs(maxLfoCount), panLFOs(maxLfoCount)          filLFOs(maxLfoCount), resLFOs(maxLfoCount), panLFOs(maxLfoCount), eqLFOs(maxLfoCount),
787            pVoice(voice)
788      {      {
789          suEndpoint.pVoice = suEndpoint.suXFInCC.pVoice = suEndpoint.suXFOutCC.pVoice = voice;          suEndpoint.pVoice = suEndpoint.suXFInCC.pVoice = suEndpoint.suXFOutCC.pVoice = suEndpoint.suPanOnCC.pVoice = voice;
790          suVolEG.pVoice = suFilEG.pVoice = suPitchEG.pVoice = voice;          suVolEG.pVoice = suFilEG.pVoice = suPitchEG.pVoice = voice;
791          suAmpLFO.pVoice = suPitchLFO.pVoice = suFilLFO.pVoice = suVolOnCC.pVoice = voice;          suAmpLFO.pVoice = suPitchLFO.pVoice = suFilLFO.pVoice = voice;
792            
793            suVolOnCC.pVoice = suPitchOnCC.pVoice = suCutoffOnCC.pVoice = suResOnCC.pVoice = voice;
794          suPitchLFO.suDepthOnCC.pVoice = suPitchLFO.suFadeEG.pVoice = suPitchLFO.suFreqOnCC.pVoice = voice;          suPitchLFO.suDepthOnCC.pVoice = suPitchLFO.suFadeEG.pVoice = suPitchLFO.suFreqOnCC.pVoice = voice;
795          suFilLFO.suFadeEG.pVoice = suFilLFO.suDepthOnCC.pVoice = suFilLFO.suFreqOnCC.pVoice = voice;          suFilLFO.suFadeEG.pVoice = suFilLFO.suDepthOnCC.pVoice = suFilLFO.suFreqOnCC.pVoice = voice;
796          suAmpLFO.suFadeEG.pVoice = suAmpLFO.suDepthOnCC.pVoice = suAmpLFO.suFreqOnCC.pVoice = voice;          suAmpLFO.suFadeEG.pVoice = suAmpLFO.suDepthOnCC.pVoice = suAmpLFO.suFreqOnCC.pVoice = voice;
# Line 642  namespace LinuxSampler { namespace sfz { Line 803  namespace LinuxSampler { namespace sfz {
803              EGs[i]->suPitchOnCC.pVoice = voice;              EGs[i]->suPitchOnCC.pVoice = voice;
804              EGs[i]->suCutoffOnCC.pVoice = voice;              EGs[i]->suCutoffOnCC.pVoice = voice;
805              EGs[i]->suResOnCC.pVoice = voice;              EGs[i]->suResOnCC.pVoice = voice;
806                EGs[i]->suPanOnCC.pVoice = voice;
807                EGs[i]->SetVoice(voice); // class EqUnitSupport
808          }          }
809                    
810          for (int i = 0; i < LFOs.capacity(); i++) {          for (int i = 0; i < LFOs.capacity(); i++) {
811              LFOs[i] = new LFOv2Unit(this);              LFOs[i] = new LFOv2Unit(this);
812              LFOs[i]->pVoice = voice;              LFOs[i]->pVoice = voice;
813                LFOs[i]->suDepthOnCC.pVoice = voice;
814                LFOs[i]->suFreqOnCC.pVoice = voice;
815              LFOs[i]->suFadeEG.pVoice = voice;              LFOs[i]->suFadeEG.pVoice = voice;
816              LFOs[i]->suVolOnCC.pVoice = voice;              LFOs[i]->suVolOnCC.pVoice = voice;
817              LFOs[i]->suPitchOnCC.pVoice = voice;              LFOs[i]->suPitchOnCC.pVoice = voice;
# Line 654  namespace LinuxSampler { namespace sfz { Line 819  namespace LinuxSampler { namespace sfz {
819              LFOs[i]->suPanOnCC.pVoice = voice;              LFOs[i]->suPanOnCC.pVoice = voice;
820              LFOs[i]->suCutoffOnCC.pVoice = voice;              LFOs[i]->suCutoffOnCC.pVoice = voice;
821              LFOs[i]->suResOnCC.pVoice = voice;              LFOs[i]->suResOnCC.pVoice = voice;
822                LFOs[i]->SetVoice(voice); // class EqUnitSupport
823          }          }
824      }      }
825            
# Line 667  namespace LinuxSampler { namespace sfz { Line 833  namespace LinuxSampler { namespace sfz {
833          }          }
834      }      }
835            
836        void SfzSignalUnitRack::InitRTLists() {
837            Pool<CCSignalUnit::CC>* pCCPool = pVoice->pEngine->pCCPool;
838            Pool<Smoother>* pSmootherPool = pVoice->pEngine->pSmootherPool;
839            
840            EqUnitSupport::InitCCLists(pCCPool, pSmootherPool);
841            
842            suVolOnCC.InitCCList(pCCPool, pSmootherPool);
843            suPitchOnCC.InitCCList(pCCPool, pSmootherPool);
844            suCutoffOnCC.InitCCList(pCCPool, pSmootherPool);
845            suResOnCC.InitCCList(pCCPool, pSmootherPool);
846            suEndpoint.suXFInCC.InitCCList(pCCPool, pSmootherPool);
847            suEndpoint.suXFOutCC.InitCCList(pCCPool, pSmootherPool);
848            suEndpoint.suPanOnCC.InitCCList(pCCPool, pSmootherPool);
849            suPitchLFO.suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
850            suPitchLFO.suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
851            suFilLFO.suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
852            suFilLFO.suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
853            suAmpLFO.suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
854            suAmpLFO.suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
855            
856            for (int i = 0; i < EGs.capacity(); i++) {
857                EGs[i]->suAmpOnCC.InitCCList(pCCPool, pSmootherPool);
858                EGs[i]->suVolOnCC.InitCCList(pCCPool, pSmootherPool);
859                EGs[i]->suPitchOnCC.InitCCList(pCCPool, pSmootherPool);
860                EGs[i]->suCutoffOnCC.InitCCList(pCCPool, pSmootherPool);
861                EGs[i]->suResOnCC.InitCCList(pCCPool, pSmootherPool);
862                EGs[i]->suPanOnCC.InitCCList(pCCPool, pSmootherPool);
863                EGs[i]->InitCCLists(pCCPool, pSmootherPool); // class EqUnitSupport
864            }
865            
866            for (int i = 0; i < LFOs.capacity(); i++) {
867                LFOs[i]->suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
868                LFOs[i]->suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
869                LFOs[i]->suVolOnCC.InitCCList(pCCPool, pSmootherPool);
870                LFOs[i]->suPitchOnCC.InitCCList(pCCPool, pSmootherPool);
871                LFOs[i]->suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
872                LFOs[i]->suPanOnCC.InitCCList(pCCPool, pSmootherPool);
873                LFOs[i]->suCutoffOnCC.InitCCList(pCCPool, pSmootherPool);
874                LFOs[i]->suResOnCC.InitCCList(pCCPool, pSmootherPool);
875                LFOs[i]->InitCCLists(pCCPool, pSmootherPool); // class EqUnitSupport
876            }
877        }
878        
879      void SfzSignalUnitRack::Trigger() {      void SfzSignalUnitRack::Trigger() {
880          EGs.clear();          EGs.clear();
881          volEGs.clear();          volEGs.clear();
882          pitchEGs.clear();          pitchEGs.clear();
883          filEGs.clear();          filEGs.clear();
884          resEGs.clear();          resEGs.clear();
885            panEGs.clear();
886            eqEGs.clear();
887                    
888          LFOs.clear();          LFOs.clear();
889          volLFOs.clear();          volLFOs.clear();
# Line 680  namespace LinuxSampler { namespace sfz { Line 891  namespace LinuxSampler { namespace sfz {
891          filLFOs.clear();          filLFOs.clear();
892          resLFOs.clear();          resLFOs.clear();
893          panLFOs.clear();          panLFOs.clear();
894            eqLFOs.clear();
895                    
896          ::sfz::Region* const pRegion = pVoice->pRegion;          ::sfz::Region* const pRegion = pVoice->pRegion;
897                    
898          suVolOnCC.SetCCs(pRegion->volume_oncc);          suVolOnCC.SetCCs(pRegion->volume_oncc);
899            suPitchOnCC.SetCCs(pRegion->pitch_oncc);
900            suCutoffOnCC.SetCCs(pRegion->cutoff_oncc);
901            suResOnCC.SetCCs(pRegion->resonance_oncc);
902                    
903          for (int i = 0; i < pRegion->eg.size(); i++) {          for (int i = 0; i < pRegion->eg.size(); i++) {
904              if (pRegion->eg[i].node.size() == 0) continue;              if (pRegion->eg[i].node.size() == 0) continue;
# Line 697  namespace LinuxSampler { namespace sfz { Line 912  namespace LinuxSampler { namespace sfz {
912                  EGs[EGs.size() - 1]->suPitchOnCC.SetCCs(pRegion->eg[i].pitch_oncc);                  EGs[EGs.size() - 1]->suPitchOnCC.SetCCs(pRegion->eg[i].pitch_oncc);
913                  EGs[EGs.size() - 1]->suCutoffOnCC.SetCCs(pRegion->eg[i].cutoff_oncc);                  EGs[EGs.size() - 1]->suCutoffOnCC.SetCCs(pRegion->eg[i].cutoff_oncc);
914                  EGs[EGs.size() - 1]->suResOnCC.SetCCs(pRegion->eg[i].resonance_oncc);                  EGs[EGs.size() - 1]->suResOnCC.SetCCs(pRegion->eg[i].resonance_oncc);
915                    EGs[EGs.size() - 1]->suPanOnCC.SetCCs(pRegion->eg[i].pan_oncc);
916                    if (pVoice->bEqSupport) {
917                        EGs[EGs.size() - 1]->suEq1FreqOnCC.SetCCs(pRegion->eg[i].eq1freq_oncc);
918                        EGs[EGs.size() - 1]->suEq2FreqOnCC.SetCCs(pRegion->eg[i].eq2freq_oncc);
919                        EGs[EGs.size() - 1]->suEq3FreqOnCC.SetCCs(pRegion->eg[i].eq3freq_oncc);
920                        EGs[EGs.size() - 1]->suEq1GainOnCC.SetCCs(pRegion->eg[i].eq1gain_oncc);
921                        EGs[EGs.size() - 1]->suEq2GainOnCC.SetCCs(pRegion->eg[i].eq2gain_oncc);
922                        EGs[EGs.size() - 1]->suEq3GainOnCC.SetCCs(pRegion->eg[i].eq3gain_oncc);
923                        EGs[EGs.size() - 1]->suEq1BwOnCC.SetCCs(pRegion->eg[i].eq1bw_oncc);
924                        EGs[EGs.size() - 1]->suEq2BwOnCC.SetCCs(pRegion->eg[i].eq2bw_oncc);
925                        EGs[EGs.size() - 1]->suEq3BwOnCC.SetCCs(pRegion->eg[i].eq3bw_oncc);
926                    }
927              } else { std::cerr << "Maximum number of EGs reached!" << std::endl; break; }              } else { std::cerr << "Maximum number of EGs reached!" << std::endl; break; }
928                            
929              if ( pRegion->eg[i].amplitude > 0 || !pRegion->eg[i].amplitude_oncc.empty() ||              if ( pRegion->eg[i].amplitude > 0 || !pRegion->eg[i].amplitude_oncc.empty() ||
# Line 720  namespace LinuxSampler { namespace sfz { Line 947  namespace LinuxSampler { namespace sfz {
947                  if(pitchEGs.size() < pitchEGs.capacity()) pitchEGs.add(EGs[EGs.size() - 1]);                  if(pitchEGs.size() < pitchEGs.capacity()) pitchEGs.add(EGs[EGs.size() - 1]);
948                  else std::cerr << "Maximum number of EGs reached!" << std::endl;                  else std::cerr << "Maximum number of EGs reached!" << std::endl;
949              }              }
950                
951                if (pRegion->eg[i].pan != 0 || !pRegion->eg[i].pan_oncc.empty()) {
952                    if(panEGs.size() < panEGs.capacity()) panEGs.add(EGs[EGs.size() - 1]);
953                    else std::cerr << "Maximum number of EGs reached!" << std::endl;
954                }
955                
956                if (pRegion->eg[i].HasEq()) {
957                    if(eqEGs.size() < eqEGs.capacity()) eqEGs.add(EGs[EGs.size() - 1]);
958                    else std::cerr << "Maximum number of EGs reached!" << std::endl;
959                }
960          }          }
961                    
962          if (pRegion->ampeg_sustain == -1) {          if (pRegion->ampeg_sustain == -1) {
# Line 729  namespace LinuxSampler { namespace sfz { Line 966  namespace LinuxSampler { namespace sfz {
966                    
967          // LFO          // LFO
968          for (int i = 0; i < pRegion->lfos.size(); i++) {          for (int i = 0; i < pRegion->lfos.size(); i++) {
969              if (pRegion->lfos[i].freq == -1) continue; // Not initialized              if (pRegion->lfos[i].freq <= 0) {
970                    if (pRegion->lfos[i].freq_oncc.empty()) continue; // Not initialized
971                    else pRegion->lfos[i].freq = 0;
972                }
973                            
974              if(LFOs.size() < LFOs.capacity()) {              if(LFOs.size() < LFOs.capacity()) {
975                  LFOv2Unit lfo(this);                  LFOv2Unit lfo(this);
# Line 741  namespace LinuxSampler { namespace sfz { Line 981  namespace LinuxSampler { namespace sfz {
981                  LFOs[LFOs.size() - 1]->suPanOnCC.SetCCs(pRegion->lfos[i].pan_oncc);                  LFOs[LFOs.size() - 1]->suPanOnCC.SetCCs(pRegion->lfos[i].pan_oncc);
982                  LFOs[LFOs.size() - 1]->suCutoffOnCC.SetCCs(pRegion->lfos[i].cutoff_oncc);                  LFOs[LFOs.size() - 1]->suCutoffOnCC.SetCCs(pRegion->lfos[i].cutoff_oncc);
983                  LFOs[LFOs.size() - 1]->suResOnCC.SetCCs(pRegion->lfos[i].resonance_oncc);                  LFOs[LFOs.size() - 1]->suResOnCC.SetCCs(pRegion->lfos[i].resonance_oncc);
984                    if (pVoice->bEqSupport) {
985                        LFOs[LFOs.size() - 1]->suEq1FreqOnCC.SetCCs(pRegion->lfos[i].eq1freq_oncc);
986                        LFOs[LFOs.size() - 1]->suEq2FreqOnCC.SetCCs(pRegion->lfos[i].eq2freq_oncc);
987                        LFOs[LFOs.size() - 1]->suEq3FreqOnCC.SetCCs(pRegion->lfos[i].eq3freq_oncc);
988                        LFOs[LFOs.size() - 1]->suEq1GainOnCC.SetCCs(pRegion->lfos[i].eq1gain_oncc);
989                        LFOs[LFOs.size() - 1]->suEq2GainOnCC.SetCCs(pRegion->lfos[i].eq2gain_oncc);
990                        LFOs[LFOs.size() - 1]->suEq3GainOnCC.SetCCs(pRegion->lfos[i].eq3gain_oncc);
991                        LFOs[LFOs.size() - 1]->suEq1BwOnCC.SetCCs(pRegion->lfos[i].eq1bw_oncc);
992                        LFOs[LFOs.size() - 1]->suEq2BwOnCC.SetCCs(pRegion->lfos[i].eq2bw_oncc);
993                        LFOs[LFOs.size() - 1]->suEq3BwOnCC.SetCCs(pRegion->lfos[i].eq3bw_oncc);
994                    }
995              } else { std::cerr << "Maximum number of LFOs reached!" << std::endl; break; }              } else { std::cerr << "Maximum number of LFOs reached!" << std::endl; break; }
996                            
997              if (pRegion->lfos[i].volume != 0 || !pRegion->lfos[i].volume_oncc.empty()) {              if (pRegion->lfos[i].volume != 0 || !pRegion->lfos[i].volume_oncc.empty()) {
# Line 767  namespace LinuxSampler { namespace sfz { Line 1018  namespace LinuxSampler { namespace sfz {
1018                  if(panLFOs.size() < panLFOs.capacity()) panLFOs.add(LFOs[LFOs.size() - 1]);                  if(panLFOs.size() < panLFOs.capacity()) panLFOs.add(LFOs[LFOs.size() - 1]);
1019                  else std::cerr << "Maximum number of LFOs reached!" << std::endl;                  else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1020              }              }
1021                
1022                if (pRegion->lfos[i].HasEq()) {
1023                    if(eqLFOs.size() < eqLFOs.capacity()) eqLFOs.add(LFOs[LFOs.size() - 1]);
1024                    else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1025                }
1026            }
1027            
1028            if (!pVoice->bEqSupport) {
1029                bHasEq = false;
1030            } else {
1031                suEq1GainOnCC.SetCCs(pRegion->eq1_gain_oncc);
1032                suEq2GainOnCC.SetCCs(pRegion->eq2_gain_oncc);
1033                suEq3GainOnCC.SetCCs(pRegion->eq3_gain_oncc);
1034                suEq1FreqOnCC.SetCCs(pRegion->eq1_freq_oncc);
1035                suEq2FreqOnCC.SetCCs(pRegion->eq2_freq_oncc);
1036                suEq3FreqOnCC.SetCCs(pRegion->eq3_freq_oncc);
1037                suEq1BwOnCC.SetCCs(pRegion->eq1_bw_oncc);
1038                suEq2BwOnCC.SetCCs(pRegion->eq2_bw_oncc);
1039                suEq3BwOnCC.SetCCs(pRegion->eq3_bw_oncc);
1040            
1041                bHasEq = pRegion->eq1_gain || pRegion->eq2_gain || pRegion->eq3_gain ||
1042                         pRegion->eq1_vel2gain || pRegion->eq2_vel2gain || pRegion->eq3_vel2gain ||
1043                         suEq1GainOnCC.HasCCs() || suEq2GainOnCC.HasCCs() || suEq3GainOnCC.HasCCs() ||
1044                         eqEGs.size() > 0 || eqLFOs.size() > 0;
1045          }          }
1046                    
1047          suPitchLFO.suDepthOnCC.SetCCs(pRegion->pitchlfo_depthcc);          suPitchLFO.suDepthOnCC.SetCCs(pRegion->pitchlfo_depthcc);
# Line 780  namespace LinuxSampler { namespace sfz { Line 1055  namespace LinuxSampler { namespace sfz {
1055                    
1056          Units.clear();          Units.clear();
1057                    
1058            EqUnitSupport::ImportUnits(this);
1059            
1060          Units.add(&suVolOnCC);          Units.add(&suVolOnCC);
1061            Units.add(&suPitchOnCC);
1062            Units.add(&suCutoffOnCC);
1063            Units.add(&suResOnCC);
1064                    
1065          Units.add(&suVolEG);          Units.add(&suVolEG);
1066          Units.add(&suFilEG);          Units.add(&suFilEG);
# Line 808  namespace LinuxSampler { namespace sfz { Line 1088  namespace LinuxSampler { namespace sfz {
1088              Units.add(&(EGs[i]->suPitchOnCC));              Units.add(&(EGs[i]->suPitchOnCC));
1089              Units.add(&(EGs[i]->suCutoffOnCC));              Units.add(&(EGs[i]->suCutoffOnCC));
1090              Units.add(&(EGs[i]->suResOnCC));              Units.add(&(EGs[i]->suResOnCC));
1091                Units.add(&(EGs[i]->suPanOnCC));
1092                EGs[i]->ImportUnits(this); // class EqUnitSupport
1093          }          }
1094                    
1095          for (int i = 0; i < LFOs.size(); i++) {          for (int i = 0; i < LFOs.size(); i++) {
# Line 819  namespace LinuxSampler { namespace sfz { Line 1101  namespace LinuxSampler { namespace sfz {
1101              Units.add(&(LFOs[i]->suPanOnCC));              Units.add(&(LFOs[i]->suPanOnCC));
1102              Units.add(&(LFOs[i]->suCutoffOnCC));              Units.add(&(LFOs[i]->suCutoffOnCC));
1103              Units.add(&(LFOs[i]->suResOnCC));              Units.add(&(LFOs[i]->suResOnCC));
1104                LFOs[i]->ImportUnits(this); // class EqUnitSupport
1105          }          }
1106                    
1107          Units.add(&suEndpoint);          Units.add(&suEndpoint);
1108          Units.add(&suEndpoint.suXFInCC);          Units.add(&suEndpoint.suXFInCC);
1109          Units.add(&suEndpoint.suXFOutCC);          Units.add(&suEndpoint.suXFOutCC);
1110            Units.add(&suEndpoint.suPanOnCC);
1111                    
1112          SignalUnitRack::Trigger();          SignalUnitRack::Trigger();
1113      }      }
# Line 839  namespace LinuxSampler { namespace sfz { Line 1123  namespace LinuxSampler { namespace sfz {
1123              volEGs[i]->EG.enterFadeOutStage();              volEGs[i]->EG.enterFadeOutStage();
1124          }          }
1125      }      }
1126    
1127        void SfzSignalUnitRack::EnterFadeOutStage(int maxFadeOutSteps) {
1128            suVolEG.EG.enterFadeOutStage(maxFadeOutSteps);
1129            for (int i = 0; i < volEGs.size(); i++) {
1130                volEGs[i]->EG.enterFadeOutStage(maxFadeOutSteps);
1131            }
1132        }
1133    
1134        void SfzSignalUnitRack::Reset() {
1135            EqUnitSupport::ResetUnits();
1136            
1137            suVolOnCC.RemoveAllCCs();
1138            suPitchOnCC.RemoveAllCCs();
1139            suCutoffOnCC.RemoveAllCCs();
1140            suResOnCC.RemoveAllCCs();
1141            suEndpoint.suXFInCC.RemoveAllCCs();
1142            suEndpoint.suXFOutCC.RemoveAllCCs();
1143            suEndpoint.suPanOnCC.RemoveAllCCs();
1144            suPitchLFO.suDepthOnCC.RemoveAllCCs();
1145            suPitchLFO.suFreqOnCC.RemoveAllCCs();
1146            suFilLFO.suDepthOnCC.RemoveAllCCs();
1147            suFilLFO.suFreqOnCC.RemoveAllCCs();
1148            suAmpLFO.suDepthOnCC.RemoveAllCCs();
1149            suAmpLFO.suFreqOnCC.RemoveAllCCs();
1150            
1151            for (int i = 0; i < EGs.capacity(); i++) {
1152                EGs[i]->suAmpOnCC.RemoveAllCCs();
1153                EGs[i]->suVolOnCC.RemoveAllCCs();
1154                EGs[i]->suPitchOnCC.RemoveAllCCs();
1155                EGs[i]->suCutoffOnCC.RemoveAllCCs();
1156                EGs[i]->suResOnCC.RemoveAllCCs();
1157                EGs[i]->suPanOnCC.RemoveAllCCs();
1158                EGs[i]->ResetUnits(); // class EqUnitSupport
1159            }
1160            
1161            for (int i = 0; i < LFOs.capacity(); i++) {
1162                LFOs[i]->suDepthOnCC.RemoveAllCCs();
1163                LFOs[i]->suFreqOnCC.RemoveAllCCs();
1164                LFOs[i]->suVolOnCC.RemoveAllCCs();
1165                LFOs[i]->suPitchOnCC.RemoveAllCCs();
1166                LFOs[i]->suFreqOnCC.RemoveAllCCs();
1167                LFOs[i]->suPanOnCC.RemoveAllCCs();
1168                LFOs[i]->suCutoffOnCC.RemoveAllCCs();
1169                LFOs[i]->suResOnCC.RemoveAllCCs();
1170                LFOs[i]->ResetUnits(); // class EqUnitSupport
1171            }
1172        }
1173    
1174        void SfzSignalUnitRack::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
1175            suVolEG.EG.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
1176            for (int i = 0; i < EGs.capacity(); i++) {
1177                EGs[i]->EG.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
1178            }
1179        }
1180        
1181        void SfzSignalUnitRack::UpdateEqSettings(EqSupport* pEqSupport) {
1182            if (!pEqSupport->HasSupport()) return;
1183            if (pEqSupport->GetBandCount() < 3) {
1184                std::cerr << "SfzSignalUnitRack::UpdateEqSettings: EQ should have at least 3 bands\n";
1185                return;
1186            }
1187            
1188            ::sfz::Region* const pRegion = pVoice->pRegion;
1189            
1190            float dB1 = (suEq1GainOnCC.Active() ? suEq1GainOnCC.GetLevel() : 0) + pRegion->eq1_gain;
1191            float dB2 = (suEq2GainOnCC.Active() ? suEq2GainOnCC.GetLevel() : 0) + pRegion->eq2_gain;
1192            float dB3 = (suEq3GainOnCC.Active() ? suEq3GainOnCC.GetLevel() : 0) + pRegion->eq3_gain;
1193            
1194            float freq1 = (suEq1FreqOnCC.Active() ? suEq1FreqOnCC.GetLevel() : 0) + pRegion->eq1_freq;
1195            float freq2 = (suEq2FreqOnCC.Active() ? suEq2FreqOnCC.GetLevel() : 0) + pRegion->eq2_freq;
1196            float freq3 = (suEq3FreqOnCC.Active() ? suEq3FreqOnCC.GetLevel() : 0) + pRegion->eq3_freq;
1197            
1198            float bw1 = (suEq1BwOnCC.Active() ? suEq1BwOnCC.GetLevel() : 0) + pRegion->eq1_bw;
1199            float bw2 = (suEq2BwOnCC.Active() ? suEq2BwOnCC.GetLevel() : 0) + pRegion->eq2_bw;
1200            float bw3 = (suEq3BwOnCC.Active() ? suEq3BwOnCC.GetLevel() : 0) + pRegion->eq3_bw;
1201            
1202            const float vel = pVoice->MIDIVelocity() / 127.0f;
1203            
1204            dB1 += pRegion->eq1_vel2gain * vel;
1205            dB2 += pRegion->eq2_vel2gain * vel;
1206            dB3 += pRegion->eq3_vel2gain * vel;
1207            
1208            freq1 += pRegion->eq1_vel2freq * vel;
1209            freq2 += pRegion->eq2_vel2freq * vel;
1210            freq3 += pRegion->eq3_vel2freq * vel;
1211            
1212            for (int i = 0; i < eqEGs.size(); i++) {
1213                EGv2Unit* eg = eqEGs[i];
1214                if (!eg->Active()) continue;
1215                
1216                float l = eg->GetLevel();
1217                dB1 += ((eg->suEq1GainOnCC.Active() ? eg->suEq1GainOnCC.GetLevel() : 0) + eg->pEGInfo->eq1gain) * l;
1218                dB2 += ((eg->suEq2GainOnCC.Active() ? eg->suEq2GainOnCC.GetLevel() : 0) + eg->pEGInfo->eq2gain) * l;
1219                dB3 += ((eg->suEq3GainOnCC.Active() ? eg->suEq3GainOnCC.GetLevel() : 0) + eg->pEGInfo->eq3gain) * l;
1220                
1221                freq1 += ((eg->suEq1FreqOnCC.Active() ? eg->suEq1FreqOnCC.GetLevel() : 0) + eg->pEGInfo->eq1freq) * l;
1222                freq2 += ((eg->suEq2FreqOnCC.Active() ? eg->suEq2FreqOnCC.GetLevel() : 0) + eg->pEGInfo->eq2freq) * l;
1223                freq3 += ((eg->suEq3FreqOnCC.Active() ? eg->suEq3FreqOnCC.GetLevel() : 0) + eg->pEGInfo->eq3freq) * l;
1224                
1225                bw1 += ((eg->suEq1BwOnCC.Active() ? eg->suEq1BwOnCC.GetLevel() : 0) + eg->pEGInfo->eq1bw) * l;
1226                bw2 += ((eg->suEq2BwOnCC.Active() ? eg->suEq2BwOnCC.GetLevel() : 0) + eg->pEGInfo->eq2bw) * l;
1227                bw3 += ((eg->suEq3BwOnCC.Active() ? eg->suEq3BwOnCC.GetLevel() : 0) + eg->pEGInfo->eq3bw) * l;
1228            }
1229            
1230            for (int i = 0; i < eqLFOs.size(); i++) {
1231                LFOv2Unit* lfo = eqLFOs[i];
1232                if (!lfo->Active()) continue;
1233                
1234                float l = lfo->GetLevel();
1235                dB1 += ((lfo->suEq1GainOnCC.Active() ? lfo->suEq1GainOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq1gain) * l;
1236                dB2 += ((lfo->suEq2GainOnCC.Active() ? lfo->suEq2GainOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq2gain) * l;
1237                dB3 += ((lfo->suEq3GainOnCC.Active() ? lfo->suEq3GainOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq3gain) * l;
1238                
1239                freq1 += ((lfo->suEq1FreqOnCC.Active() ? lfo->suEq1FreqOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq1freq) * l;
1240                freq2 += ((lfo->suEq2FreqOnCC.Active() ? lfo->suEq2FreqOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq2freq) * l;
1241                freq3 += ((lfo->suEq3FreqOnCC.Active() ? lfo->suEq3FreqOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq3freq) * l;
1242                
1243                bw1 += ((lfo->suEq1BwOnCC.Active() ? lfo->suEq1BwOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq1bw) * l;
1244                bw2 += ((lfo->suEq2BwOnCC.Active() ? lfo->suEq2BwOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq2bw) * l;
1245                bw3 += ((lfo->suEq3BwOnCC.Active() ? lfo->suEq3BwOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq3bw) * l;
1246            }
1247            
1248            pEqSupport->SetGain(0, dB1);
1249            pEqSupport->SetGain(1, dB2);
1250            pEqSupport->SetGain(2, dB3);
1251            
1252            pEqSupport->SetFreq(0, freq1);
1253            pEqSupport->SetFreq(1, freq2);
1254            pEqSupport->SetFreq(2, freq3);
1255            
1256            pEqSupport->SetBandwidth(0, bw1);
1257            pEqSupport->SetBandwidth(1, bw2);
1258            pEqSupport->SetBandwidth(2, bw3);
1259        }
1260        
1261        EqUnitSupport::EqUnitSupport(SfzSignalUnitRack* pRack, Voice* pVoice)
1262            : suEq1GainOnCC(pRack), suEq2GainOnCC(pRack), suEq3GainOnCC(pRack),
1263              suEq1FreqOnCC(pRack), suEq2FreqOnCC(pRack), suEq3FreqOnCC(pRack),
1264              suEq1BwOnCC(pRack), suEq2BwOnCC(pRack), suEq3BwOnCC(pRack)
1265        {
1266            SetVoice(pVoice);
1267        }
1268        
1269        void EqUnitSupport::SetVoice(Voice* pVoice) {
1270            suEq1GainOnCC.pVoice = suEq2GainOnCC.pVoice = suEq3GainOnCC.pVoice = pVoice;
1271            suEq1FreqOnCC.pVoice = suEq2FreqOnCC.pVoice = suEq3FreqOnCC.pVoice = pVoice;
1272            suEq1BwOnCC.pVoice = suEq2BwOnCC.pVoice = suEq3BwOnCC.pVoice = pVoice;
1273        }
1274        
1275        void EqUnitSupport::ImportUnits(SfzSignalUnitRack* pRack) {
1276            if (suEq1GainOnCC.HasCCs()) pRack->Units.add(&suEq1GainOnCC);
1277            if (suEq2GainOnCC.HasCCs()) pRack->Units.add(&suEq2GainOnCC);
1278            if (suEq3GainOnCC.HasCCs()) pRack->Units.add(&suEq3GainOnCC);
1279            if (suEq1FreqOnCC.HasCCs()) pRack->Units.add(&suEq1FreqOnCC);
1280            if (suEq2FreqOnCC.HasCCs()) pRack->Units.add(&suEq2FreqOnCC);
1281            if (suEq3FreqOnCC.HasCCs()) pRack->Units.add(&suEq3FreqOnCC);
1282            if (suEq1BwOnCC.HasCCs()) pRack->Units.add(&suEq1BwOnCC);
1283            if (suEq2BwOnCC.HasCCs()) pRack->Units.add(&suEq2BwOnCC);
1284            if (suEq3BwOnCC.HasCCs()) pRack->Units.add(&suEq3BwOnCC);
1285        }
1286        
1287        void EqUnitSupport::ResetUnits() {
1288            suEq1GainOnCC.RemoveAllCCs();
1289            suEq2GainOnCC.RemoveAllCCs();
1290            suEq3GainOnCC.RemoveAllCCs();
1291            suEq1FreqOnCC.RemoveAllCCs();
1292            suEq2FreqOnCC.RemoveAllCCs();
1293            suEq3FreqOnCC.RemoveAllCCs();
1294            suEq1BwOnCC.RemoveAllCCs();
1295            suEq2BwOnCC.RemoveAllCCs();
1296            suEq3BwOnCC.RemoveAllCCs();
1297        }
1298        
1299        void EqUnitSupport::InitCCLists(Pool<CCSignalUnit::CC>* pCCPool, Pool<Smoother>* pSmootherPool) {
1300            suEq1GainOnCC.InitCCList(pCCPool, pSmootherPool);
1301            suEq2GainOnCC.InitCCList(pCCPool, pSmootherPool);
1302            suEq3GainOnCC.InitCCList(pCCPool, pSmootherPool);
1303            suEq1FreqOnCC.InitCCList(pCCPool, pSmootherPool);
1304            suEq2FreqOnCC.InitCCList(pCCPool, pSmootherPool);
1305            suEq3FreqOnCC.InitCCList(pCCPool, pSmootherPool);
1306            suEq1BwOnCC.InitCCList(pCCPool, pSmootherPool);
1307            suEq2BwOnCC.InitCCList(pCCPool, pSmootherPool);
1308            suEq3BwOnCC.InitCCList(pCCPool, pSmootherPool);
1309        }
1310            
1311  }} // namespace LinuxSampler::sfz  }} // namespace LinuxSampler::sfz

Legend:
Removed from v.2236  
changed lines
  Added in v.3054

  ViewVC Help
Powered by ViewVC