/[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 2233 by iliev, Mon Aug 8 18:46:19 2011 UTC revision 2327 by persson, Sat Mar 10 16:16:14 2012 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 43  namespace LinuxSampler { namespace sfz { Line 49  namespace LinuxSampler { namespace sfz {
49          return f;          return f;
50      }      }
51            
52        void XFInCCUnit::SetCrossFadeCCs(::sfz::Array<int>& loCCs, ::sfz::Array<int>& hiCCs) {
53            RemoveAllCCs();
54            
55            for (int cc = 0; cc < 128; cc++) {
56                if (loCCs[cc] == 0 && hiCCs[cc] == 0) continue;
57                int i = loCCs[cc];
58                int j = hiCCs[cc];
59                if (j == 0) j = 127;
60                i += j << 8; // workaround to keep both values in the Influence parameter
61                AddCC(cc, i);
62            }
63        }
64        
65        void XFInCCUnit::Calculate() {
66            float l = 1;
67                    
68            RTList<CC>::Iterator ctrl = pCtrls->first();
69            RTList<CC>::Iterator end  = pCtrls->end();
70            for(; ctrl != end; ++ctrl) {
71                float c = 1;
72                int influence = (*ctrl).Influence;
73                int lo = influence & 0xff;
74                int hi = influence >> 8;
75                if ((*ctrl).Value <= lo) {
76                    c = 0;
77                } else if ((*ctrl).Value >= hi) {
78                    c = 1;
79                } else {
80                    float xfVelSize = hi - lo;
81                    float velPos = (*ctrl).Value - lo;
82                    c = velPos / xfVelSize;
83                    if (pVoice->pRegion->xf_cccurve == ::sfz::POWER) {
84                        c = sin(c * M_PI / 2.0);
85                    }
86                }
87                
88                l *= c;
89            }
90            
91            if (Level != l) {
92                Level = l;
93                if (pListener != NULL) pListener->ValueChanged(this);
94            }
95        }
96        
97        
98        void XFOutCCUnit::Calculate() {
99            float l = 1;
100                    
101            RTList<CC>::Iterator ctrl = pCtrls->first();
102            RTList<CC>::Iterator end  = pCtrls->end();
103            for(; ctrl != end; ++ctrl) {
104                float c = 1;
105                int influence = (*ctrl).Influence;
106                int lo = influence & 0xff;
107                int hi = influence >> 8;
108                if ((*ctrl).Value >= hi) {
109                    c = 0;
110                } else if ((*ctrl).Value <= lo) {
111                    c = 1;
112                } else {
113                    float xfVelSize = hi - lo;
114                    float velPos = (*ctrl).Value - lo;
115                    c = 1.0f - velPos / xfVelSize;
116                    if (pVoice->pRegion->xf_cccurve == ::sfz::POWER) {
117                        c = sin(c * M_PI / 2.0);
118                    }
119                }
120                
121                l *= c;
122            }
123            
124            if (Level != l) {
125                Level = l;
126                if (pListener != NULL) pListener->ValueChanged(this);
127            }
128        }
129        
130        
131        EGv2Unit::EGv2Unit(SfzSignalUnitRack* rack)
132            : EGUnit< ::LinuxSampler::sfz::EG>(rack), EqUnitSupport(rack), suAmpOnCC(rack), suVolOnCC(rack),
133              suPitchOnCC(rack), suCutoffOnCC(rack), suResOnCC(rack), suPanOnCC(rack)
134        { }
135            
136      void EGv2Unit::Trigger() {      void EGv2Unit::Trigger() {
137          egInfo = *pEGInfo;          egInfo = *pEGInfo;
# Line 59  namespace LinuxSampler { namespace sfz { Line 148  namespace LinuxSampler { namespace sfz {
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          EG.trigger(uint(pRegion->pitcheg_start * 10),          float hold = pRegion->pitcheg_hold + pRegion->pitcheg_vel2hold * velrelease;
167                     std::max(0.0, pRegion->pitcheg_attack + pRegion->pitcheg_vel2attack * velrelease),          hold = std::max(0.0f, hold + GetInfluence(pRegion->pitcheg_hold_oncc));
168                     std::max(0.0, pRegion->pitcheg_hold + pRegion->pitcheg_vel2hold * velrelease),          
169                     std::max(0.0, pRegion->pitcheg_decay + pRegion->pitcheg_vel2decay * velrelease),          float decay = pRegion->pitcheg_decay + pRegion->pitcheg_vel2decay * velrelease;
170                     uint(std::min(std::max(0.0, 10 * (pRegion->pitcheg_sustain + pRegion->pitcheg_vel2sustain * velrelease)), 1000.0)),          decay = std::max(0.0f, decay + GetInfluence(pRegion->pitcheg_decay_oncc));
171                     std::max(0.0, pRegion->pitcheg_release + pRegion->pitcheg_vel2release * velrelease),          
172                     GetSampleRate());          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 (
179                uint(std::min(std::max(0.0f, start), 1000.0f)), attack, hold, decay,
180                uint(std::min(std::max(0.0f, sustain), 1000.0f)), release, GetSampleRate(), true
181            );
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 127  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            
# Line 166  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 189  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 221  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 255  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) {      EndpointUnit::EndpointUnit(SfzSignalUnitRack* rack)
486            : EndpointSignalUnit(rack), suXFInCC(rack), suXFOutCC(rack), suPanOnCC(rack), pitchVeltrackRatio(0)
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;
532            
533            if (pVoice->MIDIVelocity <= pVoice->pRegion->xfin_lovel) {
534                xfInVelCoeff = 0;
535            } else if (pVoice->MIDIVelocity >= pVoice->pRegion->xfin_hivel) {
536                xfInVelCoeff = 1;
537            } else {
538                float xfVelSize = pVoice->pRegion->xfin_hivel - pVoice->pRegion->xfin_lovel;
539                float velPos = pVoice->MIDIVelocity - pVoice->pRegion->xfin_lovel;
540                xfInVelCoeff = velPos / xfVelSize;
541                if (pVoice->pRegion->xf_velcurve == ::sfz::POWER) {
542                    xfInVelCoeff = sin(xfInVelCoeff * M_PI / 2.0);
543                }
544            }
545            
546            float xfOutVelCoeff = 1;
547            
548            if (pVoice->MIDIVelocity >= pVoice->pRegion->xfout_hivel) {
549                if (pVoice->pRegion->xfout_lovel < 127 /* is set */) xfOutVelCoeff = 0;
550            } else if (pVoice->MIDIVelocity <= pVoice->pRegion->xfout_lovel) {
551                xfOutVelCoeff = 1;
552            } else {
553                float xfVelSize = pVoice->pRegion->xfout_hivel - pVoice->pRegion->xfout_lovel;
554                float velPos = pVoice->MIDIVelocity - pVoice->pRegion->xfout_lovel;
555                xfOutVelCoeff = 1.0f - velPos / xfVelSize;
556                if (pVoice->pRegion->xf_velcurve == ::sfz::POWER) {
557                    xfOutVelCoeff = sin(xfOutVelCoeff * M_PI / 2.0);
558                }
559            }
560            
561            float xfInKeyCoeff = 1;
562            
563            if (pVoice->MIDIKey <= pVoice->pRegion->xfin_lokey) {
564                if (pVoice->pRegion->xfin_hikey > 0 /* is set */) xfInKeyCoeff = 0;
565            } else if (pVoice->MIDIKey >= pVoice->pRegion->xfin_hikey) {
566                xfInKeyCoeff = 1;
567            } else {
568                float xfKeySize = pVoice->pRegion->xfin_hikey - pVoice->pRegion->xfin_lokey;
569                float keyPos = pVoice->MIDIKey - pVoice->pRegion->xfin_lokey;
570                xfInKeyCoeff = keyPos / xfKeySize;
571                if (pVoice->pRegion->xf_keycurve == ::sfz::POWER) {
572                    xfInKeyCoeff = sin(xfInKeyCoeff * M_PI / 2.0);
573                }
574            }
575            
576            float xfOutKeyCoeff = 1;
577            
578            if (pVoice->MIDIKey >= pVoice->pRegion->xfout_hikey) {
579                if (pVoice->pRegion->xfout_lokey < 127 /* is set */) xfOutKeyCoeff = 0;
580            } else if (pVoice->MIDIKey <= pVoice->pRegion->xfout_lokey) {
581                xfOutKeyCoeff = 1;
582            } else {
583                float xfKeySize = pVoice->pRegion->xfout_hikey - pVoice->pRegion->xfout_lokey;
584                float keyPos = pVoice->MIDIKey - pVoice->pRegion->xfout_lokey;
585                xfOutKeyCoeff = 1.0f - keyPos / xfKeySize;
586                if (pVoice->pRegion->xf_keycurve == ::sfz::POWER) {
587                    xfOutKeyCoeff = sin(xfOutKeyCoeff * M_PI / 2.0);
588                }
589            }
590            
591            xfCoeff = xfInVelCoeff * xfOutVelCoeff * xfInKeyCoeff * xfOutKeyCoeff;
592            
593            suXFInCC.SetCrossFadeCCs(pVoice->pRegion->xfin_locc, pVoice->pRegion->xfin_hicc);
594            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 335  namespace LinuxSampler { namespace sfz { Line 619  namespace LinuxSampler { namespace sfz {
619          for (int i = 0; i < GetRack()->volEGs.size(); i++) {          for (int i = 0; i < GetRack()->volEGs.size(); i++) {
620              EGv2Unit* eg = GetRack()->volEGs[i];              EGv2Unit* eg = GetRack()->volEGs[i];
621              if (!eg->Active()) continue;              if (!eg->Active()) continue;
             vol += eg->GetLevel() * (eg->pEGInfo->amplitude / 100.0f);  
622                            
623                float dB = eg->suVolOnCC.Active() ? eg->suVolOnCC.GetLevel() : -200;
624                if (dB < -144) dB = eg->pEGInfo->volume;
625                else if (eg->pEGInfo->volume >= -144) dB += eg->pEGInfo->volume;
626                
627                float amp = eg->suAmpOnCC.Active() ? eg->suAmpOnCC.GetLevel() : 0;
628                amp = (amp + eg->pEGInfo->amplitude) / 100.0f;
629                
630                if (dB >= -144) {
631                    if (amp == 0 && eg->suAmpOnCC.GetCCCount() == 0) amp = 1.0f;
632                    amp *= ToRatio(dB * 10.0);
633                }
634                
635                vol += amp * eg->GetLevel();
636          }          }
637                    
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          return vol;          if (suXFInCC.Active())  vol *= suXFInCC.GetLevel();
654            if (suXFOutCC.Active()) vol *= suXFOutCC.GetLevel();
655            return vol * xfCoeff;
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;
668                    
669            for (int i = 0; i < GetRack()->filEGs.size(); i++) {
670                EGv2Unit* eg = GetRack()->filEGs[i];
671                if (!eg->Active()) continue;
672                
673                float f = eg->suCutoffOnCC.Active() ? eg->suCutoffOnCC.GetLevel() : 0;
674                f = eg->GetLevel() * (eg->pEGInfo->cutoff + f);
675                val *= RTMath::CentsToFreqRatioUnlimited(f);
676            }
677            
678          for (int i = 0; i < GetRack()->filLFOs.size(); i++) {          for (int i = 0; i < GetRack()->filLFOs.size(); i++) {
679              LFOv2Unit* lfo = GetRack()->filLFOs[i];              LFOv2Unit* lfo = GetRack()->filLFOs[i];
680              if (!lfo->Active()) continue;              if (!lfo->Active()) continue;
# Line 380  namespace LinuxSampler { namespace sfz { Line 687  namespace LinuxSampler { namespace sfz {
687          return val;          return val;
688      }      }
689            
690        float EndpointUnit::CalculateFilterCutoff(float cutoff) {
691            cutoff *= GetFilterCutoff();
692            float maxCutoff = 0.49 * pVoice->GetSampleRate();
693            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++) {
703                EGv2Unit* eg = GetRack()->pitchEGs[i];
704                if (!eg->Active()) continue;
705                
706                float f = eg->suPitchOnCC.Active() ? eg->suPitchOnCC.GetLevel() : 0;
707                p *= RTMath::CentsToFreqRatioUnlimited(eg->GetLevel() * (eg->pEGInfo->pitch + f));
708            }
709                    
710          PitchLFOUnit* u2 = &(GetRack()->suPitchLFO);          PitchLFOUnit* u2 = &(GetRack()->suPitchLFO);
711          CCSignalUnit* u3 = &(GetRack()->suPitchLFO.suDepthOnCC);          CCSignalUnit* u3 = &(GetRack()->suPitchLFO.suDepthOnCC);
# Line 398  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++) {
730                EGv2Unit* eg = GetRack()->resEGs[i];
731                if (!eg->Active()) continue;
732                
733                float f = eg->suResOnCC.Active() ? eg->suResOnCC.GetLevel() : 0;
734                val += eg->GetLevel() * (eg->pEGInfo->resonance + f);
735            }
736                    
737          for (int i = 0; i < GetRack()->resLFOs.size(); i++) {          for (int i = 0; i < GetRack()->resLFOs.size(); i++) {
738              LFOv2Unit* lfo = GetRack()->resLFOs[i];              LFOv2Unit* lfo = GetRack()->resLFOs[i];
# Line 416  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 434  namespace LinuxSampler { namespace sfz { Line 779  namespace LinuxSampler { namespace sfz {
779            
780            
781      SfzSignalUnitRack::SfzSignalUnitRack(Voice* voice)      SfzSignalUnitRack::SfzSignalUnitRack(Voice* voice)
782          : SignalUnitRack(MaxUnitCount), pVoice(voice), suEndpoint(this), suVolEG(this), suFilEG(this), suPitchEG(this),          : SignalUnitRack(MaxUnitCount), EqUnitSupport(this, voice), pVoice(voice),
783          EGs(maxEgCount), volEGs(maxEgCount), pitchEGs(maxEgCount), suVolOnCC(this),          suEndpoint(this), suVolEG(this), suFilEG(this), suPitchEG(this),
784            EGs(maxEgCount), volEGs(maxEgCount), pitchEGs(maxEgCount), filEGs(maxEgCount),
785            resEGs(maxEgCount), panEGs(maxEgCount), eqEGs(maxEgCount),
786            suVolOnCC(this), suPitchOnCC(this), suCutoffOnCC(this), suResOnCC(this),
787          suAmpLFO(this), suPitchLFO(this), suFilLFO(this),          suAmpLFO(this), suPitchLFO(this), suFilLFO(this),
788          LFOs(maxLfoCount), volLFOs(maxLfoCount), pitchLFOs(maxLfoCount),          LFOs(maxLfoCount), volLFOs(maxLfoCount), pitchLFOs(maxLfoCount),
789          filLFOs(maxLfoCount), resLFOs(maxLfoCount), panLFOs(maxLfoCount)          filLFOs(maxLfoCount), resLFOs(maxLfoCount), panLFOs(maxLfoCount), eqLFOs(maxLfoCount)
790      {      {
791          suEndpoint.pVoice = suVolEG.pVoice = suFilEG.pVoice = suPitchEG.pVoice = voice;          suEndpoint.pVoice = suEndpoint.suXFInCC.pVoice = suEndpoint.suXFOutCC.pVoice = suEndpoint.suPanOnCC.pVoice = voice;
792          suAmpLFO.pVoice = suPitchLFO.pVoice = suFilLFO.pVoice = suVolOnCC.pVoice = voice;          suVolEG.pVoice = suFilEG.pVoice = suPitchEG.pVoice = voice;
793            suAmpLFO.pVoice = suPitchLFO.pVoice = suFilLFO.pVoice = voice;
794            
795            suVolOnCC.pVoice = suPitchOnCC.pVoice = suCutoffOnCC.pVoice = suResOnCC.pVoice = voice;
796          suPitchLFO.suDepthOnCC.pVoice = suPitchLFO.suFadeEG.pVoice = suPitchLFO.suFreqOnCC.pVoice = voice;          suPitchLFO.suDepthOnCC.pVoice = suPitchLFO.suFadeEG.pVoice = suPitchLFO.suFreqOnCC.pVoice = voice;
797          suFilLFO.suFadeEG.pVoice = suFilLFO.suDepthOnCC.pVoice = suFilLFO.suFreqOnCC.pVoice = voice;          suFilLFO.suFadeEG.pVoice = suFilLFO.suDepthOnCC.pVoice = suFilLFO.suFreqOnCC.pVoice = voice;
798          suAmpLFO.suFadeEG.pVoice = suAmpLFO.suDepthOnCC.pVoice = suAmpLFO.suFreqOnCC.pVoice = voice;          suAmpLFO.suFadeEG.pVoice = suAmpLFO.suDepthOnCC.pVoice = suAmpLFO.suFreqOnCC.pVoice = voice;
# Line 449  namespace LinuxSampler { namespace sfz { Line 800  namespace LinuxSampler { namespace sfz {
800          for (int i = 0; i < EGs.capacity(); i++) {          for (int i = 0; i < EGs.capacity(); i++) {
801              EGs[i] = new EGv2Unit(this);              EGs[i] = new EGv2Unit(this);
802              EGs[i]->pVoice = voice;              EGs[i]->pVoice = voice;
803                EGs[i]->suAmpOnCC.pVoice = voice;
804                EGs[i]->suVolOnCC.pVoice = voice;
805                EGs[i]->suPitchOnCC.pVoice = voice;
806                EGs[i]->suCutoffOnCC.pVoice = voice;
807                EGs[i]->suResOnCC.pVoice = voice;
808                EGs[i]->suPanOnCC.pVoice = voice;
809                EGs[i]->SetVoice(voice); // class EqUnitSupport
810          }          }
811                    
812          for (int i = 0; i < LFOs.capacity(); i++) {          for (int i = 0; i < LFOs.capacity(); i++) {
813              LFOs[i] = new LFOv2Unit(this);              LFOs[i] = new LFOv2Unit(this);
814              LFOs[i]->pVoice = voice;              LFOs[i]->pVoice = voice;
815                LFOs[i]->suDepthOnCC.pVoice = voice;
816                LFOs[i]->suFreqOnCC.pVoice = voice;
817              LFOs[i]->suFadeEG.pVoice = voice;              LFOs[i]->suFadeEG.pVoice = voice;
818              LFOs[i]->suVolOnCC.pVoice = voice;              LFOs[i]->suVolOnCC.pVoice = voice;
819              LFOs[i]->suPitchOnCC.pVoice = voice;              LFOs[i]->suPitchOnCC.pVoice = voice;
# Line 461  namespace LinuxSampler { namespace sfz { Line 821  namespace LinuxSampler { namespace sfz {
821              LFOs[i]->suPanOnCC.pVoice = voice;              LFOs[i]->suPanOnCC.pVoice = voice;
822              LFOs[i]->suCutoffOnCC.pVoice = voice;              LFOs[i]->suCutoffOnCC.pVoice = voice;
823              LFOs[i]->suResOnCC.pVoice = voice;              LFOs[i]->suResOnCC.pVoice = voice;
824                LFOs[i]->SetVoice(voice); // class EqUnitSupport
825          }          }
826      }      }
827            
# Line 474  namespace LinuxSampler { namespace sfz { Line 835  namespace LinuxSampler { namespace sfz {
835          }          }
836      }      }
837            
838        void SfzSignalUnitRack::InitRTLists() {
839            Pool<CCSignalUnit::CC>* pCCPool = pVoice->pEngine->pCCPool;
840            Pool<Smoother>* pSmootherPool = pVoice->pEngine->pSmootherPool;
841            
842            EqUnitSupport::InitCCLists(pCCPool, pSmootherPool);
843            
844            suVolOnCC.InitCCList(pCCPool, pSmootherPool);
845            suPitchOnCC.InitCCList(pCCPool, pSmootherPool);
846            suCutoffOnCC.InitCCList(pCCPool, pSmootherPool);
847            suResOnCC.InitCCList(pCCPool, pSmootherPool);
848            suEndpoint.suXFInCC.InitCCList(pCCPool, pSmootherPool);
849            suEndpoint.suXFOutCC.InitCCList(pCCPool, pSmootherPool);
850            suEndpoint.suPanOnCC.InitCCList(pCCPool, pSmootherPool);
851            suPitchLFO.suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
852            suPitchLFO.suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
853            suFilLFO.suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
854            suFilLFO.suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
855            suAmpLFO.suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
856            suAmpLFO.suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
857            
858            for (int i = 0; i < EGs.capacity(); i++) {
859                EGs[i]->suAmpOnCC.InitCCList(pCCPool, pSmootherPool);
860                EGs[i]->suVolOnCC.InitCCList(pCCPool, pSmootherPool);
861                EGs[i]->suPitchOnCC.InitCCList(pCCPool, pSmootherPool);
862                EGs[i]->suCutoffOnCC.InitCCList(pCCPool, pSmootherPool);
863                EGs[i]->suResOnCC.InitCCList(pCCPool, pSmootherPool);
864                EGs[i]->suPanOnCC.InitCCList(pCCPool, pSmootherPool);
865                EGs[i]->InitCCLists(pCCPool, pSmootherPool); // class EqUnitSupport
866            }
867            
868            for (int i = 0; i < LFOs.capacity(); i++) {
869                LFOs[i]->suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
870                LFOs[i]->suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
871                LFOs[i]->suVolOnCC.InitCCList(pCCPool, pSmootherPool);
872                LFOs[i]->suPitchOnCC.InitCCList(pCCPool, pSmootherPool);
873                LFOs[i]->suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
874                LFOs[i]->suPanOnCC.InitCCList(pCCPool, pSmootherPool);
875                LFOs[i]->suCutoffOnCC.InitCCList(pCCPool, pSmootherPool);
876                LFOs[i]->suResOnCC.InitCCList(pCCPool, pSmootherPool);
877                LFOs[i]->InitCCLists(pCCPool, pSmootherPool); // class EqUnitSupport
878            }
879        }
880        
881      void SfzSignalUnitRack::Trigger() {      void SfzSignalUnitRack::Trigger() {
882          EGs.clear();          EGs.clear();
883          volEGs.clear();          volEGs.clear();
884          pitchEGs.clear();          pitchEGs.clear();
885            filEGs.clear();
886            resEGs.clear();
887            panEGs.clear();
888            eqEGs.clear();
889                    
890          LFOs.clear();          LFOs.clear();
891          volLFOs.clear();          volLFOs.clear();
# Line 485  namespace LinuxSampler { namespace sfz { Line 893  namespace LinuxSampler { namespace sfz {
893          filLFOs.clear();          filLFOs.clear();
894          resLFOs.clear();          resLFOs.clear();
895          panLFOs.clear();          panLFOs.clear();
896            eqLFOs.clear();
897                    
898          ::sfz::Region* const pRegion = pVoice->pRegion;          ::sfz::Region* const pRegion = pVoice->pRegion;
899                    
900          suVolOnCC.SetCCs(pRegion->volume_oncc);          suVolOnCC.SetCCs(pRegion->volume_oncc);
901            suPitchOnCC.SetCCs(pRegion->pitch_oncc);
902            suCutoffOnCC.SetCCs(pRegion->cutoff_oncc);
903            suResOnCC.SetCCs(pRegion->resonance_oncc);
904                    
905          for (int i = 0; i < pRegion->eg.size(); i++) {          for (int i = 0; i < pRegion->eg.size(); i++) {
906              if (pRegion->eg[i].node.size() == 0) continue;              if (pRegion->eg[i].node.size() == 0) continue;
# Line 497  namespace LinuxSampler { namespace sfz { Line 909  namespace LinuxSampler { namespace sfz {
909                  EGv2Unit eg(this);                  EGv2Unit eg(this);
910                  eg.pEGInfo = &(pRegion->eg[i]);                  eg.pEGInfo = &(pRegion->eg[i]);
911                  EGs.increment()->Copy(eg);                  EGs.increment()->Copy(eg);
912                    EGs[EGs.size() - 1]->suAmpOnCC.SetCCs(pRegion->eg[i].amplitude_oncc);
913                    EGs[EGs.size() - 1]->suVolOnCC.SetCCs(pRegion->eg[i].volume_oncc);
914                    EGs[EGs.size() - 1]->suPitchOnCC.SetCCs(pRegion->eg[i].pitch_oncc);
915                    EGs[EGs.size() - 1]->suCutoffOnCC.SetCCs(pRegion->eg[i].cutoff_oncc);
916                    EGs[EGs.size() - 1]->suResOnCC.SetCCs(pRegion->eg[i].resonance_oncc);
917                    EGs[EGs.size() - 1]->suPanOnCC.SetCCs(pRegion->eg[i].pan_oncc);
918                    if (pVoice->bEqSupport) {
919                        EGs[EGs.size() - 1]->suEq1FreqOnCC.SetCCs(pRegion->eg[i].eq1freq_oncc);
920                        EGs[EGs.size() - 1]->suEq2FreqOnCC.SetCCs(pRegion->eg[i].eq2freq_oncc);
921                        EGs[EGs.size() - 1]->suEq3FreqOnCC.SetCCs(pRegion->eg[i].eq3freq_oncc);
922                        EGs[EGs.size() - 1]->suEq1GainOnCC.SetCCs(pRegion->eg[i].eq1gain_oncc);
923                        EGs[EGs.size() - 1]->suEq2GainOnCC.SetCCs(pRegion->eg[i].eq2gain_oncc);
924                        EGs[EGs.size() - 1]->suEq3GainOnCC.SetCCs(pRegion->eg[i].eq3gain_oncc);
925                        EGs[EGs.size() - 1]->suEq1BwOnCC.SetCCs(pRegion->eg[i].eq1bw_oncc);
926                        EGs[EGs.size() - 1]->suEq2BwOnCC.SetCCs(pRegion->eg[i].eq2bw_oncc);
927                        EGs[EGs.size() - 1]->suEq3BwOnCC.SetCCs(pRegion->eg[i].eq3bw_oncc);
928                    }
929              } else { std::cerr << "Maximum number of EGs reached!" << std::endl; break; }              } else { std::cerr << "Maximum number of EGs reached!" << std::endl; break; }
930                            
931              if (pRegion->eg[i].amplitude > 0) {              if ( pRegion->eg[i].amplitude > 0 || !pRegion->eg[i].amplitude_oncc.empty() ||
932                     pRegion->eg[i].volume > -145 || !pRegion->eg[i].volume_oncc.empty()
933                ) {
934                  if(volEGs.size() < volEGs.capacity()) volEGs.add(EGs[EGs.size() - 1]);                  if(volEGs.size() < volEGs.capacity()) volEGs.add(EGs[EGs.size() - 1]);
935                  else std::cerr << "Maximum number of EGs reached!" << std::endl;                  else std::cerr << "Maximum number of EGs reached!" << std::endl;
936              }              }
937                
938                if (pRegion->eg[i].cutoff != 0 || !pRegion->eg[i].cutoff_oncc.empty()) {
939                    if(filEGs.size() < filEGs.capacity()) filEGs.add(EGs[EGs.size() - 1]);
940                    else std::cerr << "Maximum number of EGs reached!" << std::endl;
941                }
942                
943                if (pRegion->eg[i].resonance != 0 || !pRegion->eg[i].resonance_oncc.empty()) {
944                    if(resEGs.size() < resEGs.capacity()) resEGs.add(EGs[EGs.size() - 1]);
945                    else std::cerr << "Maximum number of EGs reached!" << std::endl;
946                }
947                
948                if (pRegion->eg[i].pitch != 0 || !pRegion->eg[i].pitch_oncc.empty()) {
949                    if(pitchEGs.size() < pitchEGs.capacity()) pitchEGs.add(EGs[EGs.size() - 1]);
950                    else std::cerr << "Maximum number of EGs reached!" << std::endl;
951                }
952                
953                if (pRegion->eg[i].pan != 0 || !pRegion->eg[i].pan_oncc.empty()) {
954                    if(panEGs.size() < panEGs.capacity()) panEGs.add(EGs[EGs.size() - 1]);
955                    else std::cerr << "Maximum number of EGs reached!" << std::endl;
956                }
957                
958                if (pRegion->eg[i].HasEq()) {
959                    if(eqEGs.size() < eqEGs.capacity()) eqEGs.add(EGs[EGs.size() - 1]);
960                    else std::cerr << "Maximum number of EGs reached!" << std::endl;
961                }
962          }          }
963                    
964          if (pRegion->ampeg_sustain == -1) {          if (pRegion->ampeg_sustain == -1) {
# Line 512  namespace LinuxSampler { namespace sfz { Line 968  namespace LinuxSampler { namespace sfz {
968                    
969          // LFO          // LFO
970          for (int i = 0; i < pRegion->lfos.size(); i++) {          for (int i = 0; i < pRegion->lfos.size(); i++) {
971              if (pRegion->lfos[i].freq == -1) continue; // Not initialized              if (pRegion->lfos[i].freq <= 0) {
972                    if (pRegion->lfos[i].freq_oncc.empty()) continue; // Not initialized
973                    else pRegion->lfos[i].freq = 0;
974                }
975                            
976              if(LFOs.size() < LFOs.capacity()) {              if(LFOs.size() < LFOs.capacity()) {
977                  LFOv2Unit lfo(this);                  LFOv2Unit lfo(this);
# Line 524  namespace LinuxSampler { namespace sfz { Line 983  namespace LinuxSampler { namespace sfz {
983                  LFOs[LFOs.size() - 1]->suPanOnCC.SetCCs(pRegion->lfos[i].pan_oncc);                  LFOs[LFOs.size() - 1]->suPanOnCC.SetCCs(pRegion->lfos[i].pan_oncc);
984                  LFOs[LFOs.size() - 1]->suCutoffOnCC.SetCCs(pRegion->lfos[i].cutoff_oncc);                  LFOs[LFOs.size() - 1]->suCutoffOnCC.SetCCs(pRegion->lfos[i].cutoff_oncc);
985                  LFOs[LFOs.size() - 1]->suResOnCC.SetCCs(pRegion->lfos[i].resonance_oncc);                  LFOs[LFOs.size() - 1]->suResOnCC.SetCCs(pRegion->lfos[i].resonance_oncc);
986                    if (pVoice->bEqSupport) {
987                        LFOs[LFOs.size() - 1]->suEq1FreqOnCC.SetCCs(pRegion->lfos[i].eq1freq_oncc);
988                        LFOs[LFOs.size() - 1]->suEq2FreqOnCC.SetCCs(pRegion->lfos[i].eq2freq_oncc);
989                        LFOs[LFOs.size() - 1]->suEq3FreqOnCC.SetCCs(pRegion->lfos[i].eq3freq_oncc);
990                        LFOs[LFOs.size() - 1]->suEq1GainOnCC.SetCCs(pRegion->lfos[i].eq1gain_oncc);
991                        LFOs[LFOs.size() - 1]->suEq2GainOnCC.SetCCs(pRegion->lfos[i].eq2gain_oncc);
992                        LFOs[LFOs.size() - 1]->suEq3GainOnCC.SetCCs(pRegion->lfos[i].eq3gain_oncc);
993                        LFOs[LFOs.size() - 1]->suEq1BwOnCC.SetCCs(pRegion->lfos[i].eq1bw_oncc);
994                        LFOs[LFOs.size() - 1]->suEq2BwOnCC.SetCCs(pRegion->lfos[i].eq2bw_oncc);
995                        LFOs[LFOs.size() - 1]->suEq3BwOnCC.SetCCs(pRegion->lfos[i].eq3bw_oncc);
996                    }
997              } else { std::cerr << "Maximum number of LFOs reached!" << std::endl; break; }              } else { std::cerr << "Maximum number of LFOs reached!" << std::endl; break; }
998                            
999              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 550  namespace LinuxSampler { namespace sfz { Line 1020  namespace LinuxSampler { namespace sfz {
1020                  if(panLFOs.size() < panLFOs.capacity()) panLFOs.add(LFOs[LFOs.size() - 1]);                  if(panLFOs.size() < panLFOs.capacity()) panLFOs.add(LFOs[LFOs.size() - 1]);
1021                  else std::cerr << "Maximum number of LFOs reached!" << std::endl;                  else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1022              }              }
1023                
1024                if (pRegion->lfos[i].HasEq()) {
1025                    if(eqLFOs.size() < eqLFOs.capacity()) eqLFOs.add(LFOs[LFOs.size() - 1]);
1026                    else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1027                }
1028            }
1029            
1030            if (!pVoice->bEqSupport) {
1031                bHasEq = false;
1032            } else {
1033                suEq1GainOnCC.SetCCs(pRegion->eq1_gain_oncc);
1034                suEq2GainOnCC.SetCCs(pRegion->eq2_gain_oncc);
1035                suEq3GainOnCC.SetCCs(pRegion->eq3_gain_oncc);
1036                suEq1FreqOnCC.SetCCs(pRegion->eq1_freq_oncc);
1037                suEq2FreqOnCC.SetCCs(pRegion->eq2_freq_oncc);
1038                suEq3FreqOnCC.SetCCs(pRegion->eq3_freq_oncc);
1039                suEq1BwOnCC.SetCCs(pRegion->eq1_bw_oncc);
1040                suEq2BwOnCC.SetCCs(pRegion->eq2_bw_oncc);
1041                suEq3BwOnCC.SetCCs(pRegion->eq3_bw_oncc);
1042            
1043                bHasEq = pRegion->eq1_gain || pRegion->eq2_gain || pRegion->eq3_gain ||
1044                         pRegion->eq1_vel2gain || pRegion->eq2_vel2gain || pRegion->eq3_vel2gain ||
1045                         suEq1GainOnCC.HasCCs() || suEq2GainOnCC.HasCCs() || suEq3GainOnCC.HasCCs() ||
1046                         eqEGs.size() > 0 || eqLFOs.size() > 0;
1047          }          }
1048                    
1049          suPitchLFO.suDepthOnCC.SetCCs(pRegion->pitchlfo_depthcc);          suPitchLFO.suDepthOnCC.SetCCs(pRegion->pitchlfo_depthcc);
# Line 563  namespace LinuxSampler { namespace sfz { Line 1057  namespace LinuxSampler { namespace sfz {
1057                    
1058          Units.clear();          Units.clear();
1059                    
1060            EqUnitSupport::ImportUnits(this);
1061            
1062          Units.add(&suVolOnCC);          Units.add(&suVolOnCC);
1063            Units.add(&suPitchOnCC);
1064            Units.add(&suCutoffOnCC);
1065            Units.add(&suResOnCC);
1066                    
1067          Units.add(&suVolEG);          Units.add(&suVolEG);
1068          Units.add(&suFilEG);          Units.add(&suFilEG);
# Line 586  namespace LinuxSampler { namespace sfz { Line 1085  namespace LinuxSampler { namespace sfz {
1085                    
1086          for (int i = 0; i < EGs.size(); i++) {          for (int i = 0; i < EGs.size(); i++) {
1087              Units.add(EGs[i]);              Units.add(EGs[i]);
1088                Units.add(&(EGs[i]->suAmpOnCC));
1089                Units.add(&(EGs[i]->suVolOnCC));
1090                Units.add(&(EGs[i]->suPitchOnCC));
1091                Units.add(&(EGs[i]->suCutoffOnCC));
1092                Units.add(&(EGs[i]->suResOnCC));
1093                Units.add(&(EGs[i]->suPanOnCC));
1094                EGs[i]->ImportUnits(this); // class EqUnitSupport
1095          }          }
1096                    
1097          for (int i = 0; i < LFOs.size(); i++) {          for (int i = 0; i < LFOs.size(); i++) {
# Line 597  namespace LinuxSampler { namespace sfz { Line 1103  namespace LinuxSampler { namespace sfz {
1103              Units.add(&(LFOs[i]->suPanOnCC));              Units.add(&(LFOs[i]->suPanOnCC));
1104              Units.add(&(LFOs[i]->suCutoffOnCC));              Units.add(&(LFOs[i]->suCutoffOnCC));
1105              Units.add(&(LFOs[i]->suResOnCC));              Units.add(&(LFOs[i]->suResOnCC));
1106                LFOs[i]->ImportUnits(this); // class EqUnitSupport
1107          }          }
1108                    
1109          Units.add(&suEndpoint);          Units.add(&suEndpoint);
1110            Units.add(&suEndpoint.suXFInCC);
1111            Units.add(&suEndpoint.suXFOutCC);
1112            Units.add(&suEndpoint.suPanOnCC);
1113                    
1114          SignalUnitRack::Trigger();          SignalUnitRack::Trigger();
1115      }      }
# Line 615  namespace LinuxSampler { namespace sfz { Line 1125  namespace LinuxSampler { namespace sfz {
1125              volEGs[i]->EG.enterFadeOutStage();              volEGs[i]->EG.enterFadeOutStage();
1126          }          }
1127      }      }
1128    
1129        void SfzSignalUnitRack::EnterFadeOutStage(int maxFadeOutSteps) {
1130            suVolEG.EG.enterFadeOutStage(maxFadeOutSteps);
1131            for (int i = 0; i < volEGs.size(); i++) {
1132                volEGs[i]->EG.enterFadeOutStage(maxFadeOutSteps);
1133            }
1134        }
1135    
1136        void SfzSignalUnitRack::Reset() {
1137            EqUnitSupport::ResetUnits();
1138            
1139            suVolOnCC.RemoveAllCCs();
1140            suPitchOnCC.RemoveAllCCs();
1141            suCutoffOnCC.RemoveAllCCs();
1142            suResOnCC.RemoveAllCCs();
1143            suEndpoint.suXFInCC.RemoveAllCCs();
1144            suEndpoint.suXFOutCC.RemoveAllCCs();
1145            suEndpoint.suPanOnCC.RemoveAllCCs();
1146            suPitchLFO.suDepthOnCC.RemoveAllCCs();
1147            suPitchLFO.suFreqOnCC.RemoveAllCCs();
1148            suFilLFO.suDepthOnCC.RemoveAllCCs();
1149            suFilLFO.suFreqOnCC.RemoveAllCCs();
1150            suAmpLFO.suDepthOnCC.RemoveAllCCs();
1151            suAmpLFO.suFreqOnCC.RemoveAllCCs();
1152            
1153            for (int i = 0; i < EGs.capacity(); i++) {
1154                EGs[i]->suAmpOnCC.RemoveAllCCs();
1155                EGs[i]->suVolOnCC.RemoveAllCCs();
1156                EGs[i]->suPitchOnCC.RemoveAllCCs();
1157                EGs[i]->suCutoffOnCC.RemoveAllCCs();
1158                EGs[i]->suResOnCC.RemoveAllCCs();
1159                EGs[i]->suPanOnCC.RemoveAllCCs();
1160                EGs[i]->ResetUnits(); // class EqUnitSupport
1161            }
1162            
1163            for (int i = 0; i < LFOs.capacity(); i++) {
1164                LFOs[i]->suDepthOnCC.RemoveAllCCs();
1165                LFOs[i]->suFreqOnCC.RemoveAllCCs();
1166                LFOs[i]->suVolOnCC.RemoveAllCCs();
1167                LFOs[i]->suPitchOnCC.RemoveAllCCs();
1168                LFOs[i]->suFreqOnCC.RemoveAllCCs();
1169                LFOs[i]->suPanOnCC.RemoveAllCCs();
1170                LFOs[i]->suCutoffOnCC.RemoveAllCCs();
1171                LFOs[i]->suResOnCC.RemoveAllCCs();
1172                LFOs[i]->ResetUnits(); // class EqUnitSupport
1173            }
1174        }
1175    
1176        void SfzSignalUnitRack::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
1177            suVolEG.EG.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
1178            for (int i = 0; i < EGs.capacity(); i++) {
1179                EGs[i]->EG.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
1180            }
1181        }
1182        
1183        void SfzSignalUnitRack::UpdateEqSettings(EqSupport* pEqSupport) {
1184            if (!pEqSupport->HasSupport()) return;
1185            if (pEqSupport->GetBandCount() < 3) {
1186                std::cerr << "SfzSignalUnitRack::UpdateEqSettings: EQ should have at least 3 bands\n";
1187                return;
1188            }
1189            
1190            ::sfz::Region* const pRegion = pVoice->pRegion;
1191            
1192            float dB1 = (suEq1GainOnCC.Active() ? suEq1GainOnCC.GetLevel() : 0) + pRegion->eq1_gain;
1193            float dB2 = (suEq2GainOnCC.Active() ? suEq2GainOnCC.GetLevel() : 0) + pRegion->eq2_gain;
1194            float dB3 = (suEq3GainOnCC.Active() ? suEq3GainOnCC.GetLevel() : 0) + pRegion->eq3_gain;
1195            
1196            float freq1 = (suEq1FreqOnCC.Active() ? suEq1FreqOnCC.GetLevel() : 0) + pRegion->eq1_freq;
1197            float freq2 = (suEq2FreqOnCC.Active() ? suEq2FreqOnCC.GetLevel() : 0) + pRegion->eq2_freq;
1198            float freq3 = (suEq3FreqOnCC.Active() ? suEq3FreqOnCC.GetLevel() : 0) + pRegion->eq3_freq;
1199            
1200            float bw1 = (suEq1BwOnCC.Active() ? suEq1BwOnCC.GetLevel() : 0) + pRegion->eq1_bw;
1201            float bw2 = (suEq2BwOnCC.Active() ? suEq2BwOnCC.GetLevel() : 0) + pRegion->eq2_bw;
1202            float bw3 = (suEq3BwOnCC.Active() ? suEq3BwOnCC.GetLevel() : 0) + pRegion->eq3_bw;
1203            
1204            const float vel = pVoice->MIDIVelocity / 127.0f;
1205            
1206            dB1 += pRegion->eq1_vel2gain * vel;
1207            dB2 += pRegion->eq2_vel2gain * vel;
1208            dB3 += pRegion->eq3_vel2gain * vel;
1209            
1210            freq1 += pRegion->eq1_vel2freq * vel;
1211            freq2 += pRegion->eq2_vel2freq * vel;
1212            freq3 += pRegion->eq3_vel2freq * vel;
1213            
1214            for (int i = 0; i < eqEGs.size(); i++) {
1215                EGv2Unit* eg = eqEGs[i];
1216                if (!eg->Active()) continue;
1217                
1218                float l = eg->GetLevel();
1219                dB1 += ((eg->suEq1GainOnCC.Active() ? eg->suEq1GainOnCC.GetLevel() : 0) + eg->pEGInfo->eq1gain) * l;
1220                dB2 += ((eg->suEq2GainOnCC.Active() ? eg->suEq2GainOnCC.GetLevel() : 0) + eg->pEGInfo->eq2gain) * l;
1221                dB3 += ((eg->suEq3GainOnCC.Active() ? eg->suEq3GainOnCC.GetLevel() : 0) + eg->pEGInfo->eq3gain) * l;
1222                
1223                freq1 += ((eg->suEq1FreqOnCC.Active() ? eg->suEq1FreqOnCC.GetLevel() : 0) + eg->pEGInfo->eq1freq) * l;
1224                freq2 += ((eg->suEq2FreqOnCC.Active() ? eg->suEq2FreqOnCC.GetLevel() : 0) + eg->pEGInfo->eq2freq) * l;
1225                freq3 += ((eg->suEq3FreqOnCC.Active() ? eg->suEq3FreqOnCC.GetLevel() : 0) + eg->pEGInfo->eq3freq) * l;
1226                
1227                bw1 += ((eg->suEq1BwOnCC.Active() ? eg->suEq1BwOnCC.GetLevel() : 0) + eg->pEGInfo->eq1bw) * l;
1228                bw2 += ((eg->suEq2BwOnCC.Active() ? eg->suEq2BwOnCC.GetLevel() : 0) + eg->pEGInfo->eq2bw) * l;
1229                bw3 += ((eg->suEq3BwOnCC.Active() ? eg->suEq3BwOnCC.GetLevel() : 0) + eg->pEGInfo->eq3bw) * l;
1230            }
1231            
1232            for (int i = 0; i < eqLFOs.size(); i++) {
1233                LFOv2Unit* lfo = eqLFOs[i];
1234                if (!lfo->Active()) continue;
1235                
1236                float l = lfo->GetLevel();
1237                dB1 += ((lfo->suEq1GainOnCC.Active() ? lfo->suEq1GainOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq1gain) * l;
1238                dB2 += ((lfo->suEq2GainOnCC.Active() ? lfo->suEq2GainOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq2gain) * l;
1239                dB3 += ((lfo->suEq3GainOnCC.Active() ? lfo->suEq3GainOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq3gain) * l;
1240                
1241                freq1 += ((lfo->suEq1FreqOnCC.Active() ? lfo->suEq1FreqOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq1freq) * l;
1242                freq2 += ((lfo->suEq2FreqOnCC.Active() ? lfo->suEq2FreqOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq2freq) * l;
1243                freq3 += ((lfo->suEq3FreqOnCC.Active() ? lfo->suEq3FreqOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq3freq) * l;
1244                
1245                bw1 += ((lfo->suEq1BwOnCC.Active() ? lfo->suEq1BwOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq1bw) * l;
1246                bw2 += ((lfo->suEq2BwOnCC.Active() ? lfo->suEq2BwOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq2bw) * l;
1247                bw3 += ((lfo->suEq3BwOnCC.Active() ? lfo->suEq3BwOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq3bw) * l;
1248            }
1249            
1250            pEqSupport->SetGain(0, dB1);
1251            pEqSupport->SetGain(1, dB2);
1252            pEqSupport->SetGain(2, dB3);
1253            
1254            pEqSupport->SetFreq(0, freq1);
1255            pEqSupport->SetFreq(1, freq2);
1256            pEqSupport->SetFreq(2, freq3);
1257            
1258            pEqSupport->SetBandwidth(0, bw1);
1259            pEqSupport->SetBandwidth(1, bw2);
1260            pEqSupport->SetBandwidth(2, bw3);
1261        }
1262        
1263        EqUnitSupport::EqUnitSupport(SfzSignalUnitRack* pRack, Voice* pVoice)
1264            : suEq1GainOnCC(pRack), suEq2GainOnCC(pRack), suEq3GainOnCC(pRack),
1265              suEq1FreqOnCC(pRack), suEq2FreqOnCC(pRack), suEq3FreqOnCC(pRack),
1266              suEq1BwOnCC(pRack), suEq2BwOnCC(pRack), suEq3BwOnCC(pRack)
1267        {
1268            SetVoice(pVoice);
1269        }
1270        
1271        void EqUnitSupport::SetVoice(Voice* pVoice) {
1272            suEq1GainOnCC.pVoice = suEq2GainOnCC.pVoice = suEq3GainOnCC.pVoice = pVoice;
1273            suEq1FreqOnCC.pVoice = suEq2FreqOnCC.pVoice = suEq3FreqOnCC.pVoice = pVoice;
1274            suEq1BwOnCC.pVoice = suEq2BwOnCC.pVoice = suEq3BwOnCC.pVoice = pVoice;
1275        }
1276        
1277        void EqUnitSupport::ImportUnits(SfzSignalUnitRack* pRack) {
1278            if (suEq1GainOnCC.HasCCs()) pRack->Units.add(&suEq1GainOnCC);
1279            if (suEq2GainOnCC.HasCCs()) pRack->Units.add(&suEq2GainOnCC);
1280            if (suEq3GainOnCC.HasCCs()) pRack->Units.add(&suEq3GainOnCC);
1281            if (suEq1FreqOnCC.HasCCs()) pRack->Units.add(&suEq1FreqOnCC);
1282            if (suEq2FreqOnCC.HasCCs()) pRack->Units.add(&suEq2FreqOnCC);
1283            if (suEq3FreqOnCC.HasCCs()) pRack->Units.add(&suEq3FreqOnCC);
1284            if (suEq1BwOnCC.HasCCs()) pRack->Units.add(&suEq1BwOnCC);
1285            if (suEq2BwOnCC.HasCCs()) pRack->Units.add(&suEq2BwOnCC);
1286            if (suEq3BwOnCC.HasCCs()) pRack->Units.add(&suEq3BwOnCC);
1287        }
1288        
1289        void EqUnitSupport::ResetUnits() {
1290            suEq1GainOnCC.RemoveAllCCs();
1291            suEq2GainOnCC.RemoveAllCCs();
1292            suEq3GainOnCC.RemoveAllCCs();
1293            suEq1FreqOnCC.RemoveAllCCs();
1294            suEq2FreqOnCC.RemoveAllCCs();
1295            suEq3FreqOnCC.RemoveAllCCs();
1296            suEq1BwOnCC.RemoveAllCCs();
1297            suEq2BwOnCC.RemoveAllCCs();
1298            suEq3BwOnCC.RemoveAllCCs();
1299        }
1300        
1301        void EqUnitSupport::InitCCLists(Pool<CCSignalUnit::CC>* pCCPool, Pool<Smoother>* pSmootherPool) {
1302            suEq1GainOnCC.InitCCList(pCCPool, pSmootherPool);
1303            suEq2GainOnCC.InitCCList(pCCPool, pSmootherPool);
1304            suEq3GainOnCC.InitCCList(pCCPool, pSmootherPool);
1305            suEq1FreqOnCC.InitCCList(pCCPool, pSmootherPool);
1306            suEq2FreqOnCC.InitCCList(pCCPool, pSmootherPool);
1307            suEq3FreqOnCC.InitCCList(pCCPool, pSmootherPool);
1308            suEq1BwOnCC.InitCCList(pCCPool, pSmootherPool);
1309            suEq2BwOnCC.InitCCList(pCCPool, pSmootherPool);
1310            suEq3BwOnCC.InitCCList(pCCPool, pSmootherPool);
1311        }
1312            
1313  }} // namespace LinuxSampler::sfz  }} // namespace LinuxSampler::sfz

Legend:
Removed from v.2233  
changed lines
  Added in v.2327

  ViewVC Help
Powered by ViewVC