1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2011 - 2012 Grigor Iliev                                *
6  *                                                                         *
7  *   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  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the Free Software           *
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
20  *   MA  02111-1307  USA                                                   *
21  ***************************************************************************/
22 
23 #include "SfzSignalUnitRack.h"
24 #include "Engine.h"
25 
26 #define _200TH_ROOT_OF_10 1.011579454259899
27 
28 namespace LinuxSampler { namespace sfz {
29 
ToRatio(int Centibels)30     double ToRatio(int Centibels) {
31         if (Centibels == 0) return 1.0;
32         return pow(_200TH_ROOT_OF_10, Centibels);
33     }
34 
SfzSignalUnit(SfzSignalUnitRack * rack)35     SfzSignalUnit::SfzSignalUnit(SfzSignalUnitRack* rack): SignalUnit(rack), pVoice(rack->pVoice) {
36 
37     }
38 
GetSampleRate()39     double SfzSignalUnit::GetSampleRate() {
40         return pVoice->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
41     }
42 
GetInfluence(ArrayList<::sfz::CC> & cc)43     float SfzSignalUnit::GetInfluence(ArrayList< ::sfz::CC>& cc) {
44         float f = 0;
45         for (int i = 0; i < cc.size(); i++) {
46             int val = pVoice->GetControllerValue(cc[i].Controller);
47             f += (val / 127.0f) * cc[i].Influence;
48         }
49         return f;
50     }
51 
SetCrossFadeCCs(::sfz::Array<int> & loCCs,::sfz::Array<int> & hiCCs)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 
Calculate()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 
Calculate()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 
EGv2Unit(SfzSignalUnitRack * rack)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 
Trigger()136     void EGv2Unit::Trigger() {
137         egInfo = *pEGInfo;
138         for (int i = 0; i < egInfo.node.size(); i++) {
139             float f = GetInfluence(egInfo.node[i].level_oncc);
140             egInfo.node[i].level = std::min(egInfo.node[i].level + f, 1.0f);
141 
142             f = GetInfluence(egInfo.node[i].time_oncc);
143             egInfo.node[i].time = std::min(egInfo.node[i].time + f, 100.0f);
144         }
145         EG.trigger(egInfo, GetSampleRate(), pVoice->MIDIVelocity());
146     }
147 
148 
Trigger()149     void PitchEGUnit::Trigger() {
150         ::sfz::Region* const pRegion = pVoice->pRegion;
151         depth = pRegion->pitcheg_depth + GetInfluence(pRegion->pitcheg_depth_oncc);
152 
153         // the length of the decay and release curves are dependent on the velocity
154         const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity());
155 
156         // set the delay trigger
157         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 (
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 
Trigger()185     void FilEGUnit::Trigger() {
186         ::sfz::Region* const pRegion = pVoice->pRegion;
187         depth = pRegion->fileg_depth + GetInfluence(pRegion->fileg_depth_oncc);
188 
189         // the length of the decay and release curves are dependent on the velocity
190         const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity());
191 
192         // set the delay trigger
193         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 (
215             uint(std::min(std::max(0.0f, start), 1000.0f)), attack, hold, decay,
216             uint(std::min(std::max(0.0f, sustain), 1000.0f)), release, GetSampleRate(), true
217         );
218     }
219 
220 
Trigger()221     void AmpEGUnit::Trigger() {
222         ::sfz::Region* const pRegion = pVoice->pRegion;
223 
224         // the length of the decay and release curves are dependent on the velocity
225         const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity());
226 
227         // set the delay trigger
228         float delay = pRegion->ampeg_delay + pRegion->ampeg_vel2delay * velrelease;
229         delay += GetInfluence(pRegion->ampeg_delaycc);
230         uiDelayTrigger = std::max(0.0f, delay) * GetSampleRate();
231 
232         float start = (pRegion->ampeg_start + GetInfluence(pRegion->ampeg_startcc)) * 10;
233 
234         float attack = pRegion->ampeg_attack + pRegion->ampeg_vel2attack * velrelease;
235         attack = std::max(0.0f, attack + GetInfluence(pRegion->ampeg_attackcc));
236 
237         float hold = pRegion->ampeg_hold + pRegion->ampeg_vel2hold * velrelease;
238         hold = std::max(0.0f, hold + GetInfluence(pRegion->ampeg_holdcc));
239 
240         float decay = pRegion->ampeg_decay + pRegion->ampeg_vel2decay * velrelease;
241         decay = std::max(0.0f, decay + GetInfluence(pRegion->ampeg_decaycc));
242 
243         float sustain = pRegion->ampeg_sustain + pRegion->ampeg_vel2sustain * velrelease;
244         sustain = 10 * (sustain + GetInfluence(pRegion->ampeg_sustaincc));
245         if (pVoice->pNote) {
246             pVoice->pNote->Override.Sustain.applyTo(sustain);
247         }
248 
249         float release = pRegion->ampeg_release + pRegion->ampeg_vel2release * velrelease;
250         release = std::max(0.0f, release + GetInfluence(pRegion->ampeg_releasecc));
251 
252         EG.trigger (
253             uint(std::min(std::max(0.0f, start), 1000.0f)), attack, hold, decay,
254             uint(std::min(std::max(0.0f, sustain), 1000.0f)), release, GetSampleRate(), false
255         );
256     }
257 
258 
LFOUnit(SfzSignalUnitRack * rack)259     LFOUnit::LFOUnit(SfzSignalUnitRack* rack)
260         : SfzSignalUnit(rack), pLfoInfo(NULL), pLFO(NULL),
261           suFadeEG(rack), suDepthOnCC(rack), suFreqOnCC(rack, this)
262     { }
263 
LFOUnit(const LFOUnit & Unit)264     LFOUnit::LFOUnit(const LFOUnit& Unit)
265         : SfzSignalUnit(Unit), suFadeEG(static_cast<SfzSignalUnitRack*>(Unit.pRack)),
266           suDepthOnCC(static_cast<SfzSignalUnitRack*>(Unit.pRack)),
267           suFreqOnCC(static_cast<SfzSignalUnitRack*>(Unit.pRack), this)
268     {
269         Copy(Unit);
270     }
271 
Increment()272     void LFOUnit::Increment() {
273         if (DelayStage()) return;
274 
275         SignalUnit::Increment();
276 
277         Level = pLFO->Render();
278         if (suFadeEG.Active()) Level *= suFadeEG.GetLevel();
279     }
280 
Trigger()281     void LFOUnit::Trigger() {
282         //reset
283         Level = 0;
284 
285         // set the delay trigger
286         uiDelayTrigger = (pLfoInfo->delay + GetInfluence(pLfoInfo->delay_oncc)) * GetSampleRate();
287         if(pLfoInfo->fade != 0 || !pLfoInfo->fade_oncc.empty()) {
288             float f = pLfoInfo->fade;
289             f += GetInfluence(pLfoInfo->fade_oncc);
290 
291             if (f != 0) {
292                 suFadeEG.uiDelayTrigger = pLfoInfo->delay * GetSampleRate();
293                 suFadeEG.EG.trigger(0, f, 0, 0, 1000, 0, GetSampleRate(), false);
294             }
295         }
296     }
297 
ValueChanged(CCSignalUnit * pUnit)298     void LFOUnit::ValueChanged(CCSignalUnit* pUnit) {
299         if (pLFO == NULL) return;
300         pLFO->SetFrequency(std::max(0.0f, suFreqOnCC.GetLevel() + pLfoInfo->freq), GetSampleRate());
301     }
302 
303 
Trigger()304     void LFOv1Unit::Trigger() {
305         LFOUnit::Trigger();
306 
307         lfo.trigger (
308             pLfoInfo->freq + suFreqOnCC.GetLevel(),
309             LFO::start_level_mid,
310             1, 0, false, GetSampleRate()
311         );
312         lfo.updateByMIDICtrlValue(0);
313     }
314 
315 
LFOv2Unit(SfzSignalUnitRack * rack)316     LFOv2Unit::LFOv2Unit(SfzSignalUnitRack* rack)
317         : LFOUnit(rack), EqUnitSupport(rack), lfos(8), lfo0(1200.0f), lfo1(1200.0f), lfo2(1200.0f),
318           lfo3(1200.0f), lfo4(1200.0f), lfo5(1200.0f), lfo6(1200.0f), lfo7(1200.0f),
319           suVolOnCC(rack), suPitchOnCC(rack), suPanOnCC(rack), suCutoffOnCC(rack), suResOnCC(rack)
320     {
321         lfos.add(&lfo0);
322         lfos.add(&lfo1);
323         lfos.add(&lfo2);
324         lfos.add(&lfo3);
325         lfos.add(&lfo4);
326         lfos.add(&lfo5);
327         lfos.add(&lfo6);
328         lfos.add(&lfo7);
329     }
330 
Trigger()331     void LFOv2Unit::Trigger() {
332         LFOUnit::Trigger();
333 
334         if (/*pLfoInfo->wave < 0 ||*/ pLfoInfo->wave >= lfos.size()) pLFO = &lfo0;
335         else pLFO = lfos[pLfoInfo->wave];
336 
337         pLFO->Trigger (
338             pLfoInfo->freq + suFreqOnCC.GetLevel(),
339             LFO::start_level_mid,
340             1, 0, false, GetSampleRate()
341         );
342         pLFO->Update(0);
343 
344         float phase = pLfoInfo->phase + GetInfluence(pLfoInfo->phase_oncc);
345         if (phase != 0) pLFO->SetPhase(phase);
346     }
347 
Trigger()348     void AmpLFOUnit::Trigger() {
349         bActive = true;
350         ::sfz::Region* const pRegion = pVoice->pRegion;
351         pLfoInfo->delay  = pRegion->amplfo_delay + GetInfluence(pRegion->amplfo_delay_oncc);
352         pLfoInfo->freq   = pRegion->amplfo_freq;
353         pLfoInfo->fade   = pRegion->amplfo_fade + GetInfluence(pRegion->amplfo_fade_oncc);
354         pLfoInfo->volume = pRegion->amplfo_depth;
355 
356         if (pLfoInfo->freq <= 0) {
357             if (!pRegion->amplfo_freqcc.empty()) pLfoInfo->freq = 0;
358             else bActive = false;
359         }
360 
361         LFOv1Unit::Trigger();
362     }
363 
Trigger()364     void PitchLFOUnit::Trigger() {
365         bActive = true;
366         ::sfz::Region* const pRegion = pVoice->pRegion;
367         pLfoInfo->delay = pRegion->pitchlfo_delay + GetInfluence(pRegion->pitchlfo_delay_oncc);
368         pLfoInfo->freq  = pRegion->pitchlfo_freq;
369         pLfoInfo->fade  = pRegion->pitchlfo_fade + GetInfluence(pRegion->pitchlfo_fade_oncc);
370         pLfoInfo->pitch = pRegion->pitchlfo_depth;
371 
372         if (pLfoInfo->freq <= 0) {
373             if (!pRegion->pitchlfo_freqcc.empty()) pLfoInfo->freq = 0;
374             else bActive = false;
375         }
376 
377         LFOv1Unit::Trigger();
378     }
379 
Trigger()380     void FilLFOUnit::Trigger() {
381         bActive = true;
382         ::sfz::Region* const pRegion = pVoice->pRegion;
383         pLfoInfo->delay  = pRegion->fillfo_delay + GetInfluence(pRegion->fillfo_delay_oncc);
384         pLfoInfo->freq   = pRegion->fillfo_freq;
385         pLfoInfo->fade   = pRegion->fillfo_fade + GetInfluence(pRegion->fillfo_fade_oncc);
386         pLfoInfo->cutoff = pRegion->fillfo_depth;
387 
388         if (pLfoInfo->freq <= 0) {
389             if (!pRegion->fillfo_freqcc.empty()) pLfoInfo->freq = 0;
390             else bActive = false;
391         }
392 
393         LFOv1Unit::Trigger();
394     }
395 
CCUnit(SfzSignalUnitRack * rack,Listener * l)396     CCUnit::CCUnit(SfzSignalUnitRack* rack, Listener* l): CCSignalUnit(rack, l) {
397         pVoice = NULL;
398     }
399 
Trigger()400     void CCUnit::Trigger() {
401         RTList<CC>::Iterator ctrl = pCtrls->first();
402         RTList<CC>::Iterator end  = pCtrls->end();
403         for(; ctrl != end; ++ctrl) {
404             (*ctrl).Value = pVoice->GetControllerValue((*ctrl).Controller);
405             if ((*ctrl).pSmoother != NULL) {
406                 if ((*ctrl).Step > 0) {
407                     float val = Normalize((*ctrl).Value, (*ctrl).Curve) * (*ctrl).Influence;
408                     (*ctrl).pSmoother->setValue( ((int) (val / (*ctrl).Step)) * (*ctrl).Step );
409                 } else {
410                     (*ctrl).pSmoother->setValue((*ctrl).Value);
411                 }
412             }
413         }
414         CCSignalUnit::Trigger();
415     }
416 
SetCCs(::sfz::Array<int> & cc)417     void CCUnit::SetCCs(::sfz::Array<int>& cc) {
418         RemoveAllCCs();
419         for (int i = 0; i < 128; i++) {
420             if (cc[i] != 0) AddCC(i, cc[i]);
421         }
422     }
423 
SetCCs(::sfz::Array<float> & cc)424     void CCUnit::SetCCs(::sfz::Array<float>& cc) {
425         RemoveAllCCs();
426         for (int i = 0; i < 128; i++) {
427             if (cc[i] != 0) AddCC(i, cc[i]);
428         }
429     }
430 
SetCCs(ArrayList<::sfz::CC> & cc)431     void CCUnit::SetCCs(ArrayList< ::sfz::CC>& cc) {
432         RemoveAllCCs();
433         for (int i = 0; i < cc.size(); i++) {
434             if (cc[i].Influence != 0) {
435                 short int curve = cc[i].Curve;
436                 if (curve >= GetCurveCount()) curve = -1;
437                 AddSmoothCC(cc[i].Controller, cc[i].Influence, curve, cc[i].Smooth, cc[i].Step);
438             }
439         }
440     }
441 
AddSmoothCC(uint8_t Controller,float Influence,short int Curve,float Smooth,float Step)442     void CCUnit::AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth, float Step) {
443         AddCC(Controller, Influence, Curve, NULL, Step);
444     }
445 
GetCurveCount()446     int CCUnit::GetCurveCount() {
447         return (int) pVoice->pRegion->GetInstrument()->curves.size();
448     }
449 
GetCurve(int idx)450     ::sfz::Curve* CCUnit::GetCurve(int idx) {
451         return &pVoice->pRegion->GetInstrument()->curves[idx];
452     }
453 
GetSampleRate()454     double CCUnit::GetSampleRate() {
455         return pVoice->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
456     }
457 
458 
~SmoothCCUnit()459     SmoothCCUnit::~SmoothCCUnit() {
460         if (pSmoothers != NULL) delete pSmoothers;
461     }
462 
AddSmoothCC(uint8_t Controller,float Influence,short int Curve,float Smooth,float Step)463     void SmoothCCUnit::AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth, float Step) {
464         if (Smooth > 0) {
465             if (pSmoothers->poolIsEmpty()) {
466                 std::cerr << "Maximum number of smoothers reached" << std::endl;
467                 return;
468             }
469             Smoother* smoother = &(*(pSmoothers->allocAppend()));
470             smoother->trigger(Smooth / 1000.0f, GetSampleRate());
471             AddCC(Controller, Influence, Curve, smoother, Step);
472         } else {
473             AddCC(Controller, Influence, Curve, NULL, Step);
474         }
475     }
476 
InitSmoothers(Pool<Smoother> * pSmootherPool)477     void SmoothCCUnit::InitSmoothers(Pool<Smoother>* pSmootherPool) {
478         if (pSmoothers != NULL) delete pSmoothers;
479         pSmoothers = new RTList<Smoother>(pSmootherPool);
480     }
481 
InitCCList(Pool<CC> * pCCPool,Pool<Smoother> * pSmootherPool)482     void SmoothCCUnit::InitCCList(Pool<CC>* pCCPool, Pool<Smoother>* pSmootherPool) {
483         CurveCCUnit::InitCCList(pCCPool, pSmootherPool);
484         InitSmoothers(pSmootherPool);
485     }
486 
487 
EndpointUnit(SfzSignalUnitRack * rack)488     EndpointUnit::EndpointUnit(SfzSignalUnitRack* rack)
489         : EndpointSignalUnit(rack), pitchVeltrackRatio(0), suXFInCC(rack), suXFOutCC(rack), suPanOnCC(rack)
490     {
491 
492     }
493 
GetInfluence(::sfz::Array<optional<float>> & cc)494     float EndpointUnit::GetInfluence(::sfz::Array< optional<float> >& cc) {
495         float f = 0;
496         for (int i = 0; i < 128; i++) {
497             if (cc[i]) {
498                 f += (pVoice->GetControllerValue(i) / 127.0f) * (*cc[i]);
499             }
500         }
501         return f;
502     }
503 
GetInfluence(::sfz::Array<optional<int>> & cc)504     float EndpointUnit::GetInfluence(::sfz::Array< optional<int> >& cc) {
505         float f = 0;
506         for (int i = 0; i < 128; i++) {
507             if (cc[i]) {
508                 f += (pVoice->GetControllerValue(i) / 127.0f) * (*cc[i]);
509             }
510         }
511         return f;
512     }
513 
GetRack()514     SfzSignalUnitRack* const EndpointUnit::GetRack() {
515         return static_cast<SfzSignalUnitRack* const>(pRack);
516     }
517 
Trigger()518     void EndpointUnit::Trigger() {
519         uiDelayTrigger = (uint)GetInfluence(pVoice->pRegion->delay_samples_oncc);
520         if (pVoice->pRegion->delay_samples) uiDelayTrigger += *pVoice->pRegion->delay_samples;
521 
522         if (pVoice->pRegion->delay) {
523             /* here we use the device sample rate */
524             uiDelayTrigger += (uint)( (*pVoice->pRegion->delay) * pVoice->GetSampleRate() );
525         }
526 
527         if (pVoice->pRegion->delay_random) {
528             float r = pVoice->GetEngine()->Random();
529             uiDelayTrigger += (uint)( r * (*pVoice->pRegion->delay_random) * pVoice->GetSampleRate() );
530         }
531 
532         uiDelayTrigger += (uint)(GetInfluence(pVoice->pRegion->delay_oncc) * pVoice->GetSampleRate());
533 
534         float xfInVelCoeff = 1;
535 
536         if (pVoice->MIDIVelocity() <= pVoice->pRegion->xfin_lovel) {
537             xfInVelCoeff = 0;
538         } else if (pVoice->MIDIVelocity() >= pVoice->pRegion->xfin_hivel) {
539             xfInVelCoeff = 1;
540         } else {
541             float xfVelSize = pVoice->pRegion->xfin_hivel - pVoice->pRegion->xfin_lovel;
542             float velPos = pVoice->MIDIVelocity() - pVoice->pRegion->xfin_lovel;
543             xfInVelCoeff = velPos / xfVelSize;
544             if (pVoice->pRegion->xf_velcurve == ::sfz::POWER) {
545                 xfInVelCoeff = sin(xfInVelCoeff * M_PI / 2.0);
546             }
547         }
548 
549         float xfOutVelCoeff = 1;
550 
551         if (pVoice->MIDIVelocity() >= pVoice->pRegion->xfout_hivel) {
552             if (pVoice->pRegion->xfout_lovel < 127 /* is set */) xfOutVelCoeff = 0;
553         } else if (pVoice->MIDIVelocity() <= pVoice->pRegion->xfout_lovel) {
554             xfOutVelCoeff = 1;
555         } else {
556             float xfVelSize = pVoice->pRegion->xfout_hivel - pVoice->pRegion->xfout_lovel;
557             float velPos = pVoice->MIDIVelocity() - pVoice->pRegion->xfout_lovel;
558             xfOutVelCoeff = 1.0f - velPos / xfVelSize;
559             if (pVoice->pRegion->xf_velcurve == ::sfz::POWER) {
560                 xfOutVelCoeff = sin(xfOutVelCoeff * M_PI / 2.0);
561             }
562         }
563 
564         float xfInKeyCoeff = 1;
565 
566         if (pVoice->MIDIKey() <= pVoice->pRegion->xfin_lokey) {
567             if (pVoice->pRegion->xfin_hikey > 0 /* is set */) xfInKeyCoeff = 0;
568         } else if (pVoice->MIDIKey() >= pVoice->pRegion->xfin_hikey) {
569             xfInKeyCoeff = 1;
570         } else {
571             float xfKeySize = pVoice->pRegion->xfin_hikey - pVoice->pRegion->xfin_lokey;
572             float keyPos = pVoice->MIDIKey() - pVoice->pRegion->xfin_lokey;
573             xfInKeyCoeff = keyPos / xfKeySize;
574             if (pVoice->pRegion->xf_keycurve == ::sfz::POWER) {
575                 xfInKeyCoeff = sin(xfInKeyCoeff * M_PI / 2.0);
576             }
577         }
578 
579         float xfOutKeyCoeff = 1;
580 
581         if (pVoice->MIDIKey() >= pVoice->pRegion->xfout_hikey) {
582             if (pVoice->pRegion->xfout_lokey < 127 /* is set */) xfOutKeyCoeff = 0;
583         } else if (pVoice->MIDIKey() <= pVoice->pRegion->xfout_lokey) {
584             xfOutKeyCoeff = 1;
585         } else {
586             float xfKeySize = pVoice->pRegion->xfout_hikey - pVoice->pRegion->xfout_lokey;
587             float keyPos = pVoice->MIDIKey() - pVoice->pRegion->xfout_lokey;
588             xfOutKeyCoeff = 1.0f - keyPos / xfKeySize;
589             if (pVoice->pRegion->xf_keycurve == ::sfz::POWER) {
590                 xfOutKeyCoeff = sin(xfOutKeyCoeff * M_PI / 2.0);
591             }
592         }
593 
594         xfCoeff = xfInVelCoeff * xfOutVelCoeff * xfInKeyCoeff * xfOutKeyCoeff;
595 
596         suXFInCC.SetCrossFadeCCs(pVoice->pRegion->xfin_locc, pVoice->pRegion->xfin_hicc);
597         suXFOutCC.SetCrossFadeCCs(pVoice->pRegion->xfout_locc, pVoice->pRegion->xfout_hicc);
598 
599         suPanOnCC.SetCCs(pVoice->pRegion->pan_oncc);
600 
601         pitchVeltrackRatio = RTMath::CentsToFreqRatioUnlimited((pVoice->MIDIVelocity() / 127.0f) * pVoice->pRegion->pitch_veltrack);
602     }
603 
Active()604     bool EndpointUnit::Active() {
605         if (pRack->isReleaseStageEntered() && uiDelayTrigger) {
606             return false; // The key was released before the delay end, so the voice won't play at all.
607         }
608 
609         if (GetRack()->suVolEG.Active()) return true;
610 
611         bool b = false;
612         for (int i = 0; i < GetRack()->volEGs.size(); i++) {
613             if (GetRack()->volEGs[i]->Active()) { b = true; break; }
614         }
615 
616         return b;
617     }
618 
GetVolume()619     float EndpointUnit::GetVolume() {
620         float vol = GetRack()->suVolEG.Active() ? GetRack()->suVolEG.GetLevel() : 0;
621 
622         for (int i = 0; i < GetRack()->volEGs.size(); i++) {
623             EGv2Unit* eg = GetRack()->volEGs[i];
624             if (!eg->Active()) continue;
625 
626             float dB = eg->suVolOnCC.Active() ? eg->suVolOnCC.GetLevel() : -200;
627             if (dB < -144) dB = eg->pEGInfo->volume;
628             else if (eg->pEGInfo->volume >= -144) dB += eg->pEGInfo->volume;
629 
630             float amp = eg->suAmpOnCC.Active() ? eg->suAmpOnCC.GetLevel() : 0;
631             amp = (amp + eg->pEGInfo->amplitude) / 100.0f;
632 
633             if (dB >= -144) {
634                 if (amp == 0 && eg->suAmpOnCC.GetCCCount() == 0) amp = 1.0f;
635                 amp *= ToRatio(dB * 10.0);
636             }
637 
638             vol += amp * eg->GetLevel();
639         }
640 
641         AmpLFOUnit* u = &(GetRack()->suAmpLFO);
642         CCSignalUnit* u2 = &(GetRack()->suAmpLFO.suDepthOnCC);
643         float f = u2->Active() ? u2->GetLevel() : 0;
644         vol *= u->Active() ? ToRatio((u->GetLevel() * (u->pLfoInfo->volume + f) * 10.0)) : 1;
645 
646         vol *= ToRatio(GetRack()->suVolOnCC.GetLevel() * 10.0);
647 
648         for (int i = 0; i < GetRack()->volLFOs.size(); i++) {
649             LFOv2Unit* lfo = GetRack()->volLFOs[i];
650             if (!lfo->Active()) continue;
651 
652             float f = lfo->suVolOnCC.Active() ? lfo->suVolOnCC.GetLevel() : 0;
653             vol *= ToRatio(lfo->GetLevel() * (lfo->pLfoInfo->volume + f) * 10.0);
654         }
655 
656         if (suXFInCC.Active())  vol *= suXFInCC.GetLevel();
657         if (suXFOutCC.Active()) vol *= suXFOutCC.GetLevel();
658         return vol * xfCoeff;
659     }
660 
GetFilterCutoff()661     float EndpointUnit::GetFilterCutoff() {
662         float val = GetRack()->suCutoffOnCC.Active() ? RTMath::CentsToFreqRatioUnlimited(GetRack()->suCutoffOnCC.GetLevel()) : 1;
663 
664         FilLFOUnit* u = &(GetRack()->suFilLFO);
665         CCSignalUnit* u1 = &(GetRack()->suFilLFO.suDepthOnCC);
666         float f = u1->Active() ? u1->GetLevel() : 0;
667         val *= u->Active() ? RTMath::CentsToFreqRatioUnlimited(u->GetLevel() * (u->pLfoInfo->cutoff + f)) : 1;
668 
669         FilEGUnit* u2 = &(GetRack()->suFilEG);
670         val *= u2->Active() ? RTMath::CentsToFreqRatioUnlimited(u2->GetLevel() * u2->depth) : 1;
671 
672         for (int i = 0; i < GetRack()->filEGs.size(); i++) {
673             EGv2Unit* eg = GetRack()->filEGs[i];
674             if (!eg->Active()) continue;
675 
676             float f = eg->suCutoffOnCC.Active() ? eg->suCutoffOnCC.GetLevel() : 0;
677             f = eg->GetLevel() * (eg->pEGInfo->cutoff + f);
678             val *= RTMath::CentsToFreqRatioUnlimited(f);
679         }
680 
681         for (int i = 0; i < GetRack()->filLFOs.size(); i++) {
682             LFOv2Unit* lfo = GetRack()->filLFOs[i];
683             if (!lfo->Active()) continue;
684 
685             float f = lfo->suCutoffOnCC.Active() ? lfo->suCutoffOnCC.GetLevel() : 0;
686             f = lfo->GetLevel() * (lfo->pLfoInfo->cutoff + f);
687             val *= RTMath::CentsToFreqRatioUnlimited(f);
688         }
689 
690         return val;
691     }
692 
CalculateFilterCutoff(float cutoff)693     float EndpointUnit::CalculateFilterCutoff(float cutoff) {
694         cutoff *= GetFilterCutoff();
695         float maxCutoff = 0.49 * pVoice->GetSampleRate();
696         return cutoff > maxCutoff ? maxCutoff : cutoff;
697     }
698 
GetPitch()699     float EndpointUnit::GetPitch() {
700         double p = GetRack()->suPitchOnCC.Active() ? RTMath::CentsToFreqRatioUnlimited(GetRack()->suPitchOnCC.GetLevel()) : 1;
701 
702         EGv1Unit* u = &(GetRack()->suPitchEG);
703         p *= u->Active() ? RTMath::CentsToFreqRatioUnlimited(u->GetLevel() * u->depth) : 1;
704 
705         for (int i = 0; i < GetRack()->pitchEGs.size(); i++) {
706             EGv2Unit* eg = GetRack()->pitchEGs[i];
707             if (!eg->Active()) continue;
708 
709             float f = eg->suPitchOnCC.Active() ? eg->suPitchOnCC.GetLevel() : 0;
710             p *= RTMath::CentsToFreqRatioUnlimited(eg->GetLevel() * (eg->pEGInfo->pitch + f));
711         }
712 
713         PitchLFOUnit* u2 = &(GetRack()->suPitchLFO);
714         CCSignalUnit* u3 = &(GetRack()->suPitchLFO.suDepthOnCC);
715         float f = u3->Active() ? u3->GetLevel() : 0;
716         p *= u2->Active() ? RTMath::CentsToFreqRatioUnlimited(u2->GetLevel() * (u2->pLfoInfo->pitch + f)) : 1;
717 
718         for (int i = 0; i < GetRack()->pitchLFOs.size(); i++) {
719             LFOv2Unit* lfo = GetRack()->pitchLFOs[i];
720             if (!lfo->Active()) continue;
721 
722             float f = lfo->suPitchOnCC.Active() ? lfo->suPitchOnCC.GetLevel() : 0;
723             p *= RTMath::CentsToFreqRatioUnlimited(lfo->GetLevel() * (lfo->pLfoInfo->pitch + f));
724         }
725 
726         return p * pitchVeltrackRatio;
727     }
728 
GetResonance()729     float EndpointUnit::GetResonance() {
730          float val = GetRack()->suResOnCC.Active() ? GetRack()->suResOnCC.GetLevel() : 0;
731 
732         for (int i = 0; i < GetRack()->resEGs.size(); i++) {
733             EGv2Unit* eg = GetRack()->resEGs[i];
734             if (!eg->Active()) continue;
735 
736             float f = eg->suResOnCC.Active() ? eg->suResOnCC.GetLevel() : 0;
737             val += eg->GetLevel() * (eg->pEGInfo->resonance + f);
738         }
739 
740         for (int i = 0; i < GetRack()->resLFOs.size(); i++) {
741             LFOv2Unit* lfo = GetRack()->resLFOs[i];
742             if (!lfo->Active()) continue;
743 
744             float f = lfo->suResOnCC.Active() ? lfo->suResOnCC.GetLevel() : 0;
745             val += lfo->GetLevel() * (lfo->pLfoInfo->resonance + f);
746         }
747 
748         return val;
749     }
750 
GetPan()751     float EndpointUnit::GetPan() {
752         float pan = suPanOnCC.Active() ? suPanOnCC.GetLevel() : 0;
753 
754         for (int i = 0; i < GetRack()->panEGs.size(); i++) {
755             EGv2Unit* eg = GetRack()->panEGs[i];
756             if (!eg->Active()) continue;
757 
758             float f = eg->suPanOnCC.Active() ? eg->suPanOnCC.GetLevel() : 0;
759 
760             if (eg->pEGInfo->pan_curve >= 0 && eg->pEGInfo->pan_curve < suPanOnCC.GetCurveCount()) {
761                 uint8_t val = eg->GetLevel() * 127;
762                 if (val > 127) val = 127;
763                 pan += eg->pEGInfo->pan * suPanOnCC.GetCurve(eg->pEGInfo->pan_curve)->v[val] +  eg->GetLevel() * f;
764             } else {
765                 pan += eg->GetLevel() * (eg->pEGInfo->pan + f);
766             }
767         }
768 
769         for (int i = 0; i < GetRack()->panLFOs.size(); i++) {
770             LFOv2Unit* lfo = GetRack()->panLFOs[i];
771             if (!lfo->Active()) continue;
772 
773             float f = lfo->suPanOnCC.Active() ? lfo->suPanOnCC.GetLevel() : 0;
774             pan += lfo->GetLevel() * (lfo->pLfoInfo->pan + f);
775         }
776 
777         return pan;
778     }
779 
780 
SfzSignalUnitRack(Voice * voice)781     SfzSignalUnitRack::SfzSignalUnitRack(Voice* voice)
782         : SignalUnitRack(MaxUnitCount), EqUnitSupport(this, voice),
783         suEndpoint(this), suVolEG(this), suFilEG(this), suPitchEG(this),
784         suAmpLFO(this), suPitchLFO(this), suFilLFO(this),
785         suVolOnCC(this), suPitchOnCC(this), suCutoffOnCC(this), suResOnCC(this),
786         EGs(maxEgCount), volEGs(maxEgCount), pitchEGs(maxEgCount), filEGs(maxEgCount),
787         resEGs(maxEgCount), panEGs(maxEgCount), eqEGs(maxEgCount),
788         LFOs(maxLfoCount), volLFOs(maxLfoCount), pitchLFOs(maxLfoCount),
789         filLFOs(maxLfoCount), resLFOs(maxLfoCount), panLFOs(maxLfoCount), eqLFOs(maxLfoCount),
790         pVoice(voice)
791     {
792         suEndpoint.pVoice = suEndpoint.suXFInCC.pVoice = suEndpoint.suXFOutCC.pVoice = suEndpoint.suPanOnCC.pVoice = voice;
793         suVolEG.pVoice = suFilEG.pVoice = suPitchEG.pVoice = voice;
794         suAmpLFO.pVoice = suPitchLFO.pVoice = suFilLFO.pVoice = voice;
795 
796         suVolOnCC.pVoice = suPitchOnCC.pVoice = suCutoffOnCC.pVoice = suResOnCC.pVoice = voice;
797         suPitchLFO.suDepthOnCC.pVoice = suPitchLFO.suFadeEG.pVoice = suPitchLFO.suFreqOnCC.pVoice = voice;
798         suFilLFO.suFadeEG.pVoice = suFilLFO.suDepthOnCC.pVoice = suFilLFO.suFreqOnCC.pVoice = voice;
799         suAmpLFO.suFadeEG.pVoice = suAmpLFO.suDepthOnCC.pVoice = suAmpLFO.suFreqOnCC.pVoice = voice;
800 
801         for (int i = 0; i < EGs.capacity(); i++) {
802             EGs[i] = new EGv2Unit(this);
803             EGs[i]->pVoice = voice;
804             EGs[i]->suAmpOnCC.pVoice = voice;
805             EGs[i]->suVolOnCC.pVoice = voice;
806             EGs[i]->suPitchOnCC.pVoice = voice;
807             EGs[i]->suCutoffOnCC.pVoice = voice;
808             EGs[i]->suResOnCC.pVoice = voice;
809             EGs[i]->suPanOnCC.pVoice = voice;
810             EGs[i]->SetVoice(voice); // class EqUnitSupport
811         }
812 
813         for (int i = 0; i < LFOs.capacity(); i++) {
814             LFOs[i] = new LFOv2Unit(this);
815             LFOs[i]->pVoice = voice;
816             LFOs[i]->suDepthOnCC.pVoice = voice;
817             LFOs[i]->suFreqOnCC.pVoice = voice;
818             LFOs[i]->suFadeEG.pVoice = voice;
819             LFOs[i]->suVolOnCC.pVoice = voice;
820             LFOs[i]->suPitchOnCC.pVoice = voice;
821             LFOs[i]->suFreqOnCC.pVoice = voice;
822             LFOs[i]->suPanOnCC.pVoice = voice;
823             LFOs[i]->suCutoffOnCC.pVoice = voice;
824             LFOs[i]->suResOnCC.pVoice = voice;
825             LFOs[i]->SetVoice(voice); // class EqUnitSupport
826         }
827     }
828 
~SfzSignalUnitRack()829     SfzSignalUnitRack::~SfzSignalUnitRack() {
830         for (int i = 0; i < EGs.capacity(); i++) {
831             delete EGs[i]; EGs[i] = NULL;
832         }
833 
834         for (int i = 0; i < LFOs.capacity(); i++) {
835             delete LFOs[i]; LFOs[i] = NULL;
836         }
837     }
838 
InitRTLists()839     void SfzSignalUnitRack::InitRTLists() {
840         Pool<CCSignalUnit::CC>* pCCPool = pVoice->pEngine->pCCPool;
841         Pool<Smoother>* pSmootherPool = pVoice->pEngine->pSmootherPool;
842 
843         EqUnitSupport::InitCCLists(pCCPool, pSmootherPool);
844 
845         suVolOnCC.InitCCList(pCCPool, pSmootherPool);
846         suPitchOnCC.InitCCList(pCCPool, pSmootherPool);
847         suCutoffOnCC.InitCCList(pCCPool, pSmootherPool);
848         suResOnCC.InitCCList(pCCPool, pSmootherPool);
849         suEndpoint.suXFInCC.InitCCList(pCCPool, pSmootherPool);
850         suEndpoint.suXFOutCC.InitCCList(pCCPool, pSmootherPool);
851         suEndpoint.suPanOnCC.InitCCList(pCCPool, pSmootherPool);
852         suPitchLFO.suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
853         suPitchLFO.suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
854         suFilLFO.suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
855         suFilLFO.suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
856         suAmpLFO.suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
857         suAmpLFO.suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
858 
859         for (int i = 0; i < EGs.capacity(); i++) {
860             EGs[i]->suAmpOnCC.InitCCList(pCCPool, pSmootherPool);
861             EGs[i]->suVolOnCC.InitCCList(pCCPool, pSmootherPool);
862             EGs[i]->suPitchOnCC.InitCCList(pCCPool, pSmootherPool);
863             EGs[i]->suCutoffOnCC.InitCCList(pCCPool, pSmootherPool);
864             EGs[i]->suResOnCC.InitCCList(pCCPool, pSmootherPool);
865             EGs[i]->suPanOnCC.InitCCList(pCCPool, pSmootherPool);
866             EGs[i]->InitCCLists(pCCPool, pSmootherPool); // class EqUnitSupport
867         }
868 
869         for (int i = 0; i < LFOs.capacity(); i++) {
870             LFOs[i]->suDepthOnCC.InitCCList(pCCPool, pSmootherPool);
871             LFOs[i]->suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
872             LFOs[i]->suVolOnCC.InitCCList(pCCPool, pSmootherPool);
873             LFOs[i]->suPitchOnCC.InitCCList(pCCPool, pSmootherPool);
874             LFOs[i]->suFreqOnCC.InitCCList(pCCPool, pSmootherPool);
875             LFOs[i]->suPanOnCC.InitCCList(pCCPool, pSmootherPool);
876             LFOs[i]->suCutoffOnCC.InitCCList(pCCPool, pSmootherPool);
877             LFOs[i]->suResOnCC.InitCCList(pCCPool, pSmootherPool);
878             LFOs[i]->InitCCLists(pCCPool, pSmootherPool); // class EqUnitSupport
879         }
880     }
881 
Trigger()882     void SfzSignalUnitRack::Trigger() {
883         EGs.clear();
884         volEGs.clear();
885         pitchEGs.clear();
886         filEGs.clear();
887         resEGs.clear();
888         panEGs.clear();
889         eqEGs.clear();
890 
891         LFOs.clear();
892         volLFOs.clear();
893         pitchLFOs.clear();
894         filLFOs.clear();
895         resLFOs.clear();
896         panLFOs.clear();
897         eqLFOs.clear();
898 
899         ::sfz::Region* const pRegion = pVoice->pRegion;
900 
901         suVolOnCC.SetCCs(pRegion->volume_oncc);
902         suPitchOnCC.SetCCs(pRegion->pitch_oncc);
903         suCutoffOnCC.SetCCs(pRegion->cutoff_oncc);
904         suResOnCC.SetCCs(pRegion->resonance_oncc);
905 
906         for (int i = 0; i < pRegion->eg.size(); i++) {
907             if (pRegion->eg[i].node.size() == 0) continue;
908 
909             if(EGs.size() < EGs.capacity()) {
910                 EGv2Unit eg(this);
911                 eg.pEGInfo = &(pRegion->eg[i]);
912                 EGs.increment()->Copy(eg);
913                 EGs[EGs.size() - 1]->suAmpOnCC.SetCCs(pRegion->eg[i].amplitude_oncc);
914                 EGs[EGs.size() - 1]->suVolOnCC.SetCCs(pRegion->eg[i].volume_oncc);
915                 EGs[EGs.size() - 1]->suPitchOnCC.SetCCs(pRegion->eg[i].pitch_oncc);
916                 EGs[EGs.size() - 1]->suCutoffOnCC.SetCCs(pRegion->eg[i].cutoff_oncc);
917                 EGs[EGs.size() - 1]->suResOnCC.SetCCs(pRegion->eg[i].resonance_oncc);
918                 EGs[EGs.size() - 1]->suPanOnCC.SetCCs(pRegion->eg[i].pan_oncc);
919                 if (pVoice->bEqSupport) {
920                     EGs[EGs.size() - 1]->suEq1FreqOnCC.SetCCs(pRegion->eg[i].eq1freq_oncc);
921                     EGs[EGs.size() - 1]->suEq2FreqOnCC.SetCCs(pRegion->eg[i].eq2freq_oncc);
922                     EGs[EGs.size() - 1]->suEq3FreqOnCC.SetCCs(pRegion->eg[i].eq3freq_oncc);
923                     EGs[EGs.size() - 1]->suEq1GainOnCC.SetCCs(pRegion->eg[i].eq1gain_oncc);
924                     EGs[EGs.size() - 1]->suEq2GainOnCC.SetCCs(pRegion->eg[i].eq2gain_oncc);
925                     EGs[EGs.size() - 1]->suEq3GainOnCC.SetCCs(pRegion->eg[i].eq3gain_oncc);
926                     EGs[EGs.size() - 1]->suEq1BwOnCC.SetCCs(pRegion->eg[i].eq1bw_oncc);
927                     EGs[EGs.size() - 1]->suEq2BwOnCC.SetCCs(pRegion->eg[i].eq2bw_oncc);
928                     EGs[EGs.size() - 1]->suEq3BwOnCC.SetCCs(pRegion->eg[i].eq3bw_oncc);
929                 }
930             } else { std::cerr << "Maximum number of EGs reached!" << std::endl; break; }
931 
932             if ( pRegion->eg[i].amplitude > 0 || !pRegion->eg[i].amplitude_oncc.empty() ||
933                  pRegion->eg[i].volume > -145 || !pRegion->eg[i].volume_oncc.empty()
934             ) {
935                 if(volEGs.size() < volEGs.capacity()) volEGs.add(EGs[EGs.size() - 1]);
936                 else std::cerr << "Maximum number of EGs reached!" << std::endl;
937             }
938 
939             if (pRegion->eg[i].cutoff != 0 || !pRegion->eg[i].cutoff_oncc.empty()) {
940                 if(filEGs.size() < filEGs.capacity()) filEGs.add(EGs[EGs.size() - 1]);
941                 else std::cerr << "Maximum number of EGs reached!" << std::endl;
942             }
943 
944             if (pRegion->eg[i].resonance != 0 || !pRegion->eg[i].resonance_oncc.empty()) {
945                 if(resEGs.size() < resEGs.capacity()) resEGs.add(EGs[EGs.size() - 1]);
946                 else std::cerr << "Maximum number of EGs reached!" << std::endl;
947             }
948 
949             if (pRegion->eg[i].pitch != 0 || !pRegion->eg[i].pitch_oncc.empty()) {
950                 if(pitchEGs.size() < pitchEGs.capacity()) pitchEGs.add(EGs[EGs.size() - 1]);
951                 else std::cerr << "Maximum number of EGs reached!" << std::endl;
952             }
953 
954             if (pRegion->eg[i].pan != 0 || !pRegion->eg[i].pan_oncc.empty()) {
955                 if(panEGs.size() < panEGs.capacity()) panEGs.add(EGs[EGs.size() - 1]);
956                 else std::cerr << "Maximum number of EGs reached!" << std::endl;
957             }
958 
959             if (pRegion->eg[i].HasEq()) {
960                 if(eqEGs.size() < eqEGs.capacity()) eqEGs.add(EGs[EGs.size() - 1]);
961                 else std::cerr << "Maximum number of EGs reached!" << std::endl;
962             }
963         }
964 
965         if (pRegion->ampeg_sustain == -1) {
966             if (volEGs.size() > 0) pRegion->ampeg_sustain = 0;
967             else pRegion->ampeg_sustain = 100;
968         }
969 
970         // LFO
971         for (int i = 0; i < pRegion->lfos.size(); i++) {
972             if (pRegion->lfos[i].freq <= 0) {
973                 if (pRegion->lfos[i].freq_oncc.empty()) continue; // Not initialized
974                 else pRegion->lfos[i].freq = 0;
975             }
976 
977             if(LFOs.size() < LFOs.capacity()) {
978                 LFOv2Unit lfo(this);
979                 lfo.pLfoInfo = &(pRegion->lfos[i]);
980                 LFOs.increment()->Copy(lfo);
981                 LFOs[LFOs.size() - 1]->suVolOnCC.SetCCs(pRegion->lfos[i].volume_oncc);
982                 LFOs[LFOs.size() - 1]->suPitchOnCC.SetCCs(pRegion->lfos[i].pitch_oncc);
983                 LFOs[LFOs.size() - 1]->suFreqOnCC.SetCCs(pRegion->lfos[i].freq_oncc);
984                 LFOs[LFOs.size() - 1]->suPanOnCC.SetCCs(pRegion->lfos[i].pan_oncc);
985                 LFOs[LFOs.size() - 1]->suCutoffOnCC.SetCCs(pRegion->lfos[i].cutoff_oncc);
986                 LFOs[LFOs.size() - 1]->suResOnCC.SetCCs(pRegion->lfos[i].resonance_oncc);
987                 if (pVoice->bEqSupport) {
988                     LFOs[LFOs.size() - 1]->suEq1FreqOnCC.SetCCs(pRegion->lfos[i].eq1freq_oncc);
989                     LFOs[LFOs.size() - 1]->suEq2FreqOnCC.SetCCs(pRegion->lfos[i].eq2freq_oncc);
990                     LFOs[LFOs.size() - 1]->suEq3FreqOnCC.SetCCs(pRegion->lfos[i].eq3freq_oncc);
991                     LFOs[LFOs.size() - 1]->suEq1GainOnCC.SetCCs(pRegion->lfos[i].eq1gain_oncc);
992                     LFOs[LFOs.size() - 1]->suEq2GainOnCC.SetCCs(pRegion->lfos[i].eq2gain_oncc);
993                     LFOs[LFOs.size() - 1]->suEq3GainOnCC.SetCCs(pRegion->lfos[i].eq3gain_oncc);
994                     LFOs[LFOs.size() - 1]->suEq1BwOnCC.SetCCs(pRegion->lfos[i].eq1bw_oncc);
995                     LFOs[LFOs.size() - 1]->suEq2BwOnCC.SetCCs(pRegion->lfos[i].eq2bw_oncc);
996                     LFOs[LFOs.size() - 1]->suEq3BwOnCC.SetCCs(pRegion->lfos[i].eq3bw_oncc);
997                 }
998             } else { std::cerr << "Maximum number of LFOs reached!" << std::endl; break; }
999 
1000             if (pRegion->lfos[i].volume != 0 || !pRegion->lfos[i].volume_oncc.empty()) {
1001                 if(volLFOs.size() < volLFOs.capacity()) volLFOs.add(LFOs[LFOs.size() - 1]);
1002                 else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1003             }
1004 
1005             if (pRegion->lfos[i].pitch != 0 || !pRegion->lfos[i].pitch_oncc.empty()) {
1006                 if(pitchLFOs.size() < pitchLFOs.capacity()) pitchLFOs.add(LFOs[LFOs.size() - 1]);
1007                 else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1008             }
1009 
1010             if (pRegion->lfos[i].cutoff != 0 || !pRegion->lfos[i].cutoff_oncc.empty()) {
1011                 if(filLFOs.size() < filLFOs.capacity()) filLFOs.add(LFOs[LFOs.size() - 1]);
1012                 else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1013             }
1014 
1015             if (pRegion->lfos[i].resonance != 0 || !pRegion->lfos[i].resonance_oncc.empty()) {
1016                 if(resLFOs.size() < resLFOs.capacity()) resLFOs.add(LFOs[LFOs.size() - 1]);
1017                 else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1018             }
1019 
1020             if (pRegion->lfos[i].pan != 0 || !pRegion->lfos[i].pan_oncc.empty()) {
1021                 if(panLFOs.size() < panLFOs.capacity()) panLFOs.add(LFOs[LFOs.size() - 1]);
1022                 else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1023             }
1024 
1025             if (pRegion->lfos[i].HasEq()) {
1026                 if(eqLFOs.size() < eqLFOs.capacity()) eqLFOs.add(LFOs[LFOs.size() - 1]);
1027                 else std::cerr << "Maximum number of LFOs reached!" << std::endl;
1028             }
1029         }
1030 
1031         if (!pVoice->bEqSupport) {
1032             bHasEq = false;
1033         } else {
1034             suEq1GainOnCC.SetCCs(pRegion->eq1_gain_oncc);
1035             suEq2GainOnCC.SetCCs(pRegion->eq2_gain_oncc);
1036             suEq3GainOnCC.SetCCs(pRegion->eq3_gain_oncc);
1037             suEq1FreqOnCC.SetCCs(pRegion->eq1_freq_oncc);
1038             suEq2FreqOnCC.SetCCs(pRegion->eq2_freq_oncc);
1039             suEq3FreqOnCC.SetCCs(pRegion->eq3_freq_oncc);
1040             suEq1BwOnCC.SetCCs(pRegion->eq1_bw_oncc);
1041             suEq2BwOnCC.SetCCs(pRegion->eq2_bw_oncc);
1042             suEq3BwOnCC.SetCCs(pRegion->eq3_bw_oncc);
1043 
1044             bHasEq = pRegion->eq1_gain || pRegion->eq2_gain || pRegion->eq3_gain ||
1045                      pRegion->eq1_vel2gain || pRegion->eq2_vel2gain || pRegion->eq3_vel2gain ||
1046                      suEq1GainOnCC.HasCCs() || suEq2GainOnCC.HasCCs() || suEq3GainOnCC.HasCCs() ||
1047                      eqEGs.size() > 0 || eqLFOs.size() > 0;
1048         }
1049 
1050         suPitchLFO.suDepthOnCC.SetCCs(pRegion->pitchlfo_depthcc);
1051         suPitchLFO.suFreqOnCC.SetCCs(pRegion->pitchlfo_freqcc);
1052 
1053         suFilLFO.suDepthOnCC.SetCCs(pRegion->fillfo_depthcc);
1054         suFilLFO.suFreqOnCC.SetCCs(pRegion->fillfo_freqcc);
1055 
1056         suAmpLFO.suDepthOnCC.SetCCs(pRegion->amplfo_depthcc);
1057         suAmpLFO.suFreqOnCC.SetCCs(pRegion->amplfo_freqcc);
1058 
1059         Units.clear();
1060 
1061         EqUnitSupport::ImportUnits(this);
1062 
1063         Units.add(&suVolOnCC);
1064         Units.add(&suPitchOnCC);
1065         Units.add(&suCutoffOnCC);
1066         Units.add(&suResOnCC);
1067 
1068         Units.add(&suVolEG);
1069         Units.add(&suFilEG);
1070         Units.add(&suPitchEG);
1071 
1072         Units.add(&suPitchLFO.suFreqOnCC); // Don't change order! (should be triggered before the LFO)
1073         Units.add(&suPitchLFO);
1074         Units.add(&suPitchLFO.suDepthOnCC);
1075         Units.add(&suPitchLFO.suFadeEG);
1076 
1077         Units.add(&suAmpLFO.suFreqOnCC); // Don't change order! (should be triggered before the LFO)
1078         Units.add(&suAmpLFO.suDepthOnCC);
1079         Units.add(&suAmpLFO);
1080         Units.add(&suAmpLFO.suFadeEG);
1081 
1082         Units.add(&suFilLFO.suFreqOnCC); // Don't change order! (should be triggered before the LFO)
1083         Units.add(&suFilLFO.suDepthOnCC);
1084         Units.add(&suFilLFO);
1085         Units.add(&suFilLFO.suFadeEG);
1086 
1087         for (int i = 0; i < EGs.size(); i++) {
1088             Units.add(EGs[i]);
1089             Units.add(&(EGs[i]->suAmpOnCC));
1090             Units.add(&(EGs[i]->suVolOnCC));
1091             Units.add(&(EGs[i]->suPitchOnCC));
1092             Units.add(&(EGs[i]->suCutoffOnCC));
1093             Units.add(&(EGs[i]->suResOnCC));
1094             Units.add(&(EGs[i]->suPanOnCC));
1095             EGs[i]->ImportUnits(this); // class EqUnitSupport
1096         }
1097 
1098         for (int i = 0; i < LFOs.size(); i++) {
1099             Units.add(&(LFOs[i]->suFreqOnCC)); // Don't change order! (should be triggered before the LFO)
1100             Units.add(LFOs[i]);
1101             Units.add(&(LFOs[i]->suFadeEG));
1102             Units.add(&(LFOs[i]->suVolOnCC));
1103             Units.add(&(LFOs[i]->suPitchOnCC));
1104             Units.add(&(LFOs[i]->suPanOnCC));
1105             Units.add(&(LFOs[i]->suCutoffOnCC));
1106             Units.add(&(LFOs[i]->suResOnCC));
1107             LFOs[i]->ImportUnits(this); // class EqUnitSupport
1108         }
1109 
1110         Units.add(&suEndpoint);
1111         Units.add(&suEndpoint.suXFInCC);
1112         Units.add(&suEndpoint.suXFOutCC);
1113         Units.add(&suEndpoint.suPanOnCC);
1114 
1115         SignalUnitRack::Trigger();
1116     }
1117 
GetEndpointUnit()1118     EndpointSignalUnit* SfzSignalUnitRack::GetEndpointUnit() {
1119         return &suEndpoint;
1120     }
1121 
EnterFadeOutStage()1122     void SfzSignalUnitRack::EnterFadeOutStage() {
1123         suVolEG.EG.enterFadeOutStage();
1124 
1125         for (int i = 0; i < volEGs.size(); i++) {
1126             volEGs[i]->EG.enterFadeOutStage();
1127         }
1128     }
1129 
EnterFadeOutStage(int maxFadeOutSteps)1130     void SfzSignalUnitRack::EnterFadeOutStage(int maxFadeOutSteps) {
1131         suVolEG.EG.enterFadeOutStage(maxFadeOutSteps);
1132         for (int i = 0; i < volEGs.size(); i++) {
1133             volEGs[i]->EG.enterFadeOutStage(maxFadeOutSteps);
1134         }
1135     }
1136 
Reset()1137     void SfzSignalUnitRack::Reset() {
1138         EqUnitSupport::ResetUnits();
1139 
1140         suVolOnCC.RemoveAllCCs();
1141         suPitchOnCC.RemoveAllCCs();
1142         suCutoffOnCC.RemoveAllCCs();
1143         suResOnCC.RemoveAllCCs();
1144         suEndpoint.suXFInCC.RemoveAllCCs();
1145         suEndpoint.suXFOutCC.RemoveAllCCs();
1146         suEndpoint.suPanOnCC.RemoveAllCCs();
1147         suPitchLFO.suDepthOnCC.RemoveAllCCs();
1148         suPitchLFO.suFreqOnCC.RemoveAllCCs();
1149         suFilLFO.suDepthOnCC.RemoveAllCCs();
1150         suFilLFO.suFreqOnCC.RemoveAllCCs();
1151         suAmpLFO.suDepthOnCC.RemoveAllCCs();
1152         suAmpLFO.suFreqOnCC.RemoveAllCCs();
1153 
1154         for (int i = 0; i < EGs.capacity(); i++) {
1155             EGs[i]->suAmpOnCC.RemoveAllCCs();
1156             EGs[i]->suVolOnCC.RemoveAllCCs();
1157             EGs[i]->suPitchOnCC.RemoveAllCCs();
1158             EGs[i]->suCutoffOnCC.RemoveAllCCs();
1159             EGs[i]->suResOnCC.RemoveAllCCs();
1160             EGs[i]->suPanOnCC.RemoveAllCCs();
1161             EGs[i]->ResetUnits(); // class EqUnitSupport
1162         }
1163 
1164         for (int i = 0; i < LFOs.capacity(); i++) {
1165             LFOs[i]->suDepthOnCC.RemoveAllCCs();
1166             LFOs[i]->suFreqOnCC.RemoveAllCCs();
1167             LFOs[i]->suVolOnCC.RemoveAllCCs();
1168             LFOs[i]->suPitchOnCC.RemoveAllCCs();
1169             LFOs[i]->suFreqOnCC.RemoveAllCCs();
1170             LFOs[i]->suPanOnCC.RemoveAllCCs();
1171             LFOs[i]->suCutoffOnCC.RemoveAllCCs();
1172             LFOs[i]->suResOnCC.RemoveAllCCs();
1173             LFOs[i]->ResetUnits(); // class EqUnitSupport
1174         }
1175     }
1176 
CalculateFadeOutCoeff(float FadeOutTime,float SampleRate)1177     void SfzSignalUnitRack::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
1178         suVolEG.EG.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
1179         for (int i = 0; i < EGs.capacity(); i++) {
1180             EGs[i]->EG.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
1181         }
1182     }
1183 
UpdateEqSettings(EqSupport * pEqSupport)1184     void SfzSignalUnitRack::UpdateEqSettings(EqSupport* pEqSupport) {
1185         if (!pEqSupport->HasSupport()) return;
1186         if (pEqSupport->GetBandCount() < 3) {
1187             std::cerr << "SfzSignalUnitRack::UpdateEqSettings: EQ should have at least 3 bands\n";
1188             return;
1189         }
1190 
1191         ::sfz::Region* const pRegion = pVoice->pRegion;
1192 
1193         float dB1 = (suEq1GainOnCC.Active() ? suEq1GainOnCC.GetLevel() : 0) + pRegion->eq1_gain;
1194         float dB2 = (suEq2GainOnCC.Active() ? suEq2GainOnCC.GetLevel() : 0) + pRegion->eq2_gain;
1195         float dB3 = (suEq3GainOnCC.Active() ? suEq3GainOnCC.GetLevel() : 0) + pRegion->eq3_gain;
1196 
1197         float freq1 = (suEq1FreqOnCC.Active() ? suEq1FreqOnCC.GetLevel() : 0) + pRegion->eq1_freq;
1198         float freq2 = (suEq2FreqOnCC.Active() ? suEq2FreqOnCC.GetLevel() : 0) + pRegion->eq2_freq;
1199         float freq3 = (suEq3FreqOnCC.Active() ? suEq3FreqOnCC.GetLevel() : 0) + pRegion->eq3_freq;
1200 
1201         float bw1 = (suEq1BwOnCC.Active() ? suEq1BwOnCC.GetLevel() : 0) + pRegion->eq1_bw;
1202         float bw2 = (suEq2BwOnCC.Active() ? suEq2BwOnCC.GetLevel() : 0) + pRegion->eq2_bw;
1203         float bw3 = (suEq3BwOnCC.Active() ? suEq3BwOnCC.GetLevel() : 0) + pRegion->eq3_bw;
1204 
1205         const float vel = pVoice->MIDIVelocity() / 127.0f;
1206 
1207         dB1 += pRegion->eq1_vel2gain * vel;
1208         dB2 += pRegion->eq2_vel2gain * vel;
1209         dB3 += pRegion->eq3_vel2gain * vel;
1210 
1211         freq1 += pRegion->eq1_vel2freq * vel;
1212         freq2 += pRegion->eq2_vel2freq * vel;
1213         freq3 += pRegion->eq3_vel2freq * vel;
1214 
1215         for (int i = 0; i < eqEGs.size(); i++) {
1216             EGv2Unit* eg = eqEGs[i];
1217             if (!eg->Active()) continue;
1218 
1219             float l = eg->GetLevel();
1220             dB1 += ((eg->suEq1GainOnCC.Active() ? eg->suEq1GainOnCC.GetLevel() : 0) + eg->pEGInfo->eq1gain) * l;
1221             dB2 += ((eg->suEq2GainOnCC.Active() ? eg->suEq2GainOnCC.GetLevel() : 0) + eg->pEGInfo->eq2gain) * l;
1222             dB3 += ((eg->suEq3GainOnCC.Active() ? eg->suEq3GainOnCC.GetLevel() : 0) + eg->pEGInfo->eq3gain) * l;
1223 
1224             freq1 += ((eg->suEq1FreqOnCC.Active() ? eg->suEq1FreqOnCC.GetLevel() : 0) + eg->pEGInfo->eq1freq) * l;
1225             freq2 += ((eg->suEq2FreqOnCC.Active() ? eg->suEq2FreqOnCC.GetLevel() : 0) + eg->pEGInfo->eq2freq) * l;
1226             freq3 += ((eg->suEq3FreqOnCC.Active() ? eg->suEq3FreqOnCC.GetLevel() : 0) + eg->pEGInfo->eq3freq) * l;
1227 
1228             bw1 += ((eg->suEq1BwOnCC.Active() ? eg->suEq1BwOnCC.GetLevel() : 0) + eg->pEGInfo->eq1bw) * l;
1229             bw2 += ((eg->suEq2BwOnCC.Active() ? eg->suEq2BwOnCC.GetLevel() : 0) + eg->pEGInfo->eq2bw) * l;
1230             bw3 += ((eg->suEq3BwOnCC.Active() ? eg->suEq3BwOnCC.GetLevel() : 0) + eg->pEGInfo->eq3bw) * l;
1231         }
1232 
1233         for (int i = 0; i < eqLFOs.size(); i++) {
1234             LFOv2Unit* lfo = eqLFOs[i];
1235             if (!lfo->Active()) continue;
1236 
1237             float l = lfo->GetLevel();
1238             dB1 += ((lfo->suEq1GainOnCC.Active() ? lfo->suEq1GainOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq1gain) * l;
1239             dB2 += ((lfo->suEq2GainOnCC.Active() ? lfo->suEq2GainOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq2gain) * l;
1240             dB3 += ((lfo->suEq3GainOnCC.Active() ? lfo->suEq3GainOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq3gain) * l;
1241 
1242             freq1 += ((lfo->suEq1FreqOnCC.Active() ? lfo->suEq1FreqOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq1freq) * l;
1243             freq2 += ((lfo->suEq2FreqOnCC.Active() ? lfo->suEq2FreqOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq2freq) * l;
1244             freq3 += ((lfo->suEq3FreqOnCC.Active() ? lfo->suEq3FreqOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq3freq) * l;
1245 
1246             bw1 += ((lfo->suEq1BwOnCC.Active() ? lfo->suEq1BwOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq1bw) * l;
1247             bw2 += ((lfo->suEq2BwOnCC.Active() ? lfo->suEq2BwOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq2bw) * l;
1248             bw3 += ((lfo->suEq3BwOnCC.Active() ? lfo->suEq3BwOnCC.GetLevel() : 0) + lfo->pLfoInfo->eq3bw) * l;
1249         }
1250 
1251         pEqSupport->SetGain(0, dB1);
1252         pEqSupport->SetGain(1, dB2);
1253         pEqSupport->SetGain(2, dB3);
1254 
1255         pEqSupport->SetFreq(0, freq1);
1256         pEqSupport->SetFreq(1, freq2);
1257         pEqSupport->SetFreq(2, freq3);
1258 
1259         pEqSupport->SetBandwidth(0, bw1);
1260         pEqSupport->SetBandwidth(1, bw2);
1261         pEqSupport->SetBandwidth(2, bw3);
1262     }
1263 
EqUnitSupport(SfzSignalUnitRack * pRack,Voice * pVoice)1264     EqUnitSupport::EqUnitSupport(SfzSignalUnitRack* pRack, Voice* pVoice)
1265         : suEq1GainOnCC(pRack), suEq2GainOnCC(pRack), suEq3GainOnCC(pRack),
1266           suEq1FreqOnCC(pRack), suEq2FreqOnCC(pRack), suEq3FreqOnCC(pRack),
1267           suEq1BwOnCC(pRack), suEq2BwOnCC(pRack), suEq3BwOnCC(pRack)
1268     {
1269         SetVoice(pVoice);
1270     }
1271 
SetVoice(Voice * pVoice)1272     void EqUnitSupport::SetVoice(Voice* pVoice) {
1273         suEq1GainOnCC.pVoice = suEq2GainOnCC.pVoice = suEq3GainOnCC.pVoice = pVoice;
1274         suEq1FreqOnCC.pVoice = suEq2FreqOnCC.pVoice = suEq3FreqOnCC.pVoice = pVoice;
1275         suEq1BwOnCC.pVoice = suEq2BwOnCC.pVoice = suEq3BwOnCC.pVoice = pVoice;
1276     }
1277 
ImportUnits(SfzSignalUnitRack * pRack)1278     void EqUnitSupport::ImportUnits(SfzSignalUnitRack* pRack) {
1279         if (suEq1GainOnCC.HasCCs()) pRack->Units.add(&suEq1GainOnCC);
1280         if (suEq2GainOnCC.HasCCs()) pRack->Units.add(&suEq2GainOnCC);
1281         if (suEq3GainOnCC.HasCCs()) pRack->Units.add(&suEq3GainOnCC);
1282         if (suEq1FreqOnCC.HasCCs()) pRack->Units.add(&suEq1FreqOnCC);
1283         if (suEq2FreqOnCC.HasCCs()) pRack->Units.add(&suEq2FreqOnCC);
1284         if (suEq3FreqOnCC.HasCCs()) pRack->Units.add(&suEq3FreqOnCC);
1285         if (suEq1BwOnCC.HasCCs()) pRack->Units.add(&suEq1BwOnCC);
1286         if (suEq2BwOnCC.HasCCs()) pRack->Units.add(&suEq2BwOnCC);
1287         if (suEq3BwOnCC.HasCCs()) pRack->Units.add(&suEq3BwOnCC);
1288     }
1289 
ResetUnits()1290     void EqUnitSupport::ResetUnits() {
1291         suEq1GainOnCC.RemoveAllCCs();
1292         suEq2GainOnCC.RemoveAllCCs();
1293         suEq3GainOnCC.RemoveAllCCs();
1294         suEq1FreqOnCC.RemoveAllCCs();
1295         suEq2FreqOnCC.RemoveAllCCs();
1296         suEq3FreqOnCC.RemoveAllCCs();
1297         suEq1BwOnCC.RemoveAllCCs();
1298         suEq2BwOnCC.RemoveAllCCs();
1299         suEq3BwOnCC.RemoveAllCCs();
1300     }
1301 
InitCCLists(Pool<CCSignalUnit::CC> * pCCPool,Pool<Smoother> * pSmootherPool)1302     void EqUnitSupport::InitCCLists(Pool<CCSignalUnit::CC>* pCCPool, Pool<Smoother>* pSmootherPool) {
1303         suEq1GainOnCC.InitCCList(pCCPool, pSmootherPool);
1304         suEq2GainOnCC.InitCCList(pCCPool, pSmootherPool);
1305         suEq3GainOnCC.InitCCList(pCCPool, pSmootherPool);
1306         suEq1FreqOnCC.InitCCList(pCCPool, pSmootherPool);
1307         suEq2FreqOnCC.InitCCList(pCCPool, pSmootherPool);
1308         suEq3FreqOnCC.InitCCList(pCCPool, pSmootherPool);
1309         suEq1BwOnCC.InitCCList(pCCPool, pSmootherPool);
1310         suEq2BwOnCC.InitCCList(pCCPool, pSmootherPool);
1311         suEq3BwOnCC.InitCCList(pCCPool, pSmootherPool);
1312     }
1313 
1314 }} // namespace LinuxSampler::sfz
1315