/[svn]/linuxsampler/trunk/src/engines/sf2/SF2SignalUnitRack.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/sf2/SF2SignalUnitRack.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2207 - (hide annotations) (download)
Fri Jul 15 15:43:49 2011 UTC (12 years, 9 months ago) by iliev
File size: 10996 byte(s)
* simplified the signal unit model
* sf2: initial implementation of modulation LFO and cutoff filter

1 iliev 2205 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2011 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 "SF2SignalUnitRack.h"
24     #include "Voice.h"
25    
26     namespace LinuxSampler { namespace sf2 {
27    
28     void EGUnit::EnterReleaseStage() {
29     update(EG::event_release, pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
30     }
31    
32     void EGUnit::CancelRelease() {
33     update(EG::event_cancel_release, pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
34     }
35    
36    
37     void VolEGUnit::Trigger() {
38     // set the delay trigger
39     double d = pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
40     uiDelayTrigger = pOwner->pRegion->GetEG1PreAttackDelay(pOwner->pPresetRegion) * d;
41     ////////////
42 iliev 2207
43     // GetEG1Sustain gets the decrease in level in centibels
44     uint sustain = ::sf2::ToRatio(-1 * pOwner->pRegion->GetEG1Sustain(pOwner->pPresetRegion)) * 1000; // in permille
45    
46 iliev 2205 trigger (
47     0, // should be in permille
48     pOwner->pRegion->GetEG1Attack(pOwner->pPresetRegion),
49     pOwner->pRegion->GetEG1Hold(pOwner->pPresetRegion),
50     pOwner->pRegion->GetEG1Decay(pOwner->pPresetRegion),
51 iliev 2207 sustain,
52 iliev 2205 pOwner->pRegion->GetEG1Release(pOwner->pPresetRegion),
53     pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
54     );
55     }
56    
57     void VolEGUnit::Increment() {
58     if (DelayStage()) return;
59    
60     EGUnit::Increment();
61     if (!active()) return;
62    
63     switch (getSegmentType()) {
64     case EG::segment_lin:
65     processLin();
66     break;
67     case EG::segment_exp:
68     processExp();
69     break;
70     case EG::segment_end:
71     getLevel();
72     break; // noop
73     case EG::segment_pow:
74     processPow();
75     break;
76     }
77    
78     if (active()) {
79    
80     // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
81     /*if (pOwner->SmplInfo.HasLoops && pOwner->Pos <= pOwner->SmplInfo.LoopStart && pOwner->SmplInfo.LoopStart < newPos) {
82     update(EG::event_hold_end, pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
83     }*/
84     // TODO: ^^^
85    
86     increment(1);
87     if (!toStageEndLeft()) update(EG::event_stage_end, pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
88     }
89     }
90    
91     void ModEGUnit::Trigger() {
92     double d = pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
93     uiDelayTrigger = pOwner->pRegion->GetEG2PreAttackDelay(pOwner->pPresetRegion) * d;
94    
95     trigger (
96     0, // should be in permille
97     pOwner->pRegion->GetEG2Attack(pOwner->pPresetRegion),
98     pOwner->pRegion->GetEG2Hold(pOwner->pPresetRegion),
99     pOwner->pRegion->GetEG2Decay(pOwner->pPresetRegion),
100 iliev 2207 uint(1000 - pOwner->pRegion->GetEG2Sustain(pOwner->pPresetRegion)),
101 iliev 2205 pOwner->pRegion->GetEG2Release(pOwner->pPresetRegion),
102     pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
103     );
104     }
105    
106     void ModEGUnit::Increment() {
107     if (DelayStage()) return;
108    
109     EGUnit::Increment();
110     if (!active()) return;
111    
112     switch (getSegmentType()) {
113     case EG::segment_lin:
114     processLin();
115     break;
116     case EG::segment_exp:
117     processExp();
118     break;
119     case EG::segment_end:
120     getLevel();
121     break; // noop
122     case EG::segment_pow:
123     processPow();
124     break;
125     }
126    
127     if (active()) {
128     increment(1);
129     if (!toStageEndLeft()) update(EG::event_stage_end, pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
130     }
131     }
132    
133    
134 iliev 2207 void ModLfoUnit::Trigger() {
135     //reset
136     Level = 0;
137    
138     // set the delay trigger
139     double samplerate = pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
140     uiDelayTrigger = pOwner->pRegion->GetDelayModLfo(pOwner->pPresetRegion) * samplerate;
141     ////////////
142    
143     trigger (
144     pOwner->pRegion->GetFreqModLfo(pOwner->pPresetRegion),
145     start_level_min,
146     1, 0, false, samplerate
147     );
148     update(0);
149     }
150    
151     void ModLfoUnit::Increment() {
152     if (DelayStage()) return;
153    
154     SignalUnitBase<Voice>::Increment();
155    
156     Level = render();
157     }
158    
159    
160 iliev 2205 void VibLfoUnit::Trigger() {
161 iliev 2207 //reset
162     Level = 0;
163    
164 iliev 2205 // set the delay trigger
165     double samplerate = pOwner->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
166     uiDelayTrigger = pOwner->pRegion->GetDelayVibLfo(pOwner->pPresetRegion) * samplerate;
167     ////////////
168    
169     trigger (
170     pOwner->pRegion->GetFreqVibLfo(pOwner->pPresetRegion),
171     start_level_min,
172     pOwner->pRegion->GetVibLfoToPitch(pOwner->pPresetRegion),
173     0, false, samplerate
174     );
175     update(0);
176     }
177 iliev 2207
178 iliev 2205 void VibLfoUnit::Increment() {
179     if (DelayStage()) return;
180    
181     SignalUnitBase<Voice>::Increment();
182    
183     Level = render();
184     }
185    
186 iliev 2207
187     EndpointUnit::EndpointUnit() {
188 iliev 2205
189     }
190 iliev 2207
191     void EndpointUnit::Trigger() {
192     prmModEgPitch->Coeff = pOwner->pRegion->GetModEnvToPitch(pOwner->pPresetRegion);
193     if (prmModEgPitch->Coeff == ::sf2::NONE) prmModEgPitch->Coeff = 0;
194    
195     prmModEgCutoff->Coeff = pOwner->pRegion->GetModEnvToFilterFc(pOwner->pPresetRegion); // cents
196     if (prmModEgCutoff->Coeff == ::sf2::NONE) prmModEgCutoff->Coeff = 0;
197    
198     prmModLfoVol->Coeff = pOwner->pRegion->GetModLfoToVolume(pOwner->pPresetRegion); // centibels
199     if (prmModLfoVol->Coeff == ::sf2::NONE) prmModLfoVol->Coeff = 0;
200    
201     prmModLfoCutoff->Coeff = pOwner->pRegion->GetModLfoToFilterFc(pOwner->pPresetRegion);
202     if (prmModLfoCutoff->Coeff == ::sf2::NONE) prmModLfoCutoff->Coeff = 0;
203    
204     prmModLfoPitch->Coeff = pOwner->pRegion->GetModLfoToPitch(pOwner->pPresetRegion);
205     if (prmModLfoPitch->Coeff == ::sf2::NONE) prmModLfoPitch->Coeff = 0;
206     }
207 iliev 2205
208     bool EndpointUnit::Active() {
209     if (Params.size() < 1) return false;
210 iliev 2207 return prmVolEg->pUnit->Active(); // volEGUnit
211 iliev 2205 }
212    
213     float EndpointUnit::GetVolume() {
214 iliev 2207 if (!prmVolEg->pUnit->Active()) return 0;
215     return prmVolEg->GetValue() *
216     ::sf2::ToRatio(prmModLfoVol->GetValue() /*logarithmically modified */);
217 iliev 2205 }
218    
219     float EndpointUnit::GetFilterCutoff() {
220 iliev 2207 double modEg, modLfo;
221     modEg = prmModEgCutoff->pUnit->Active() ? prmModEgCutoff->GetValue() : 0;
222     modEg = RTMath::CentsToFreqRatioUnlimited(modEg);
223    
224     modLfo = prmModLfoCutoff->pUnit->Active() ? prmModLfoCutoff->GetValue() : 0;
225     modLfo = RTMath::CentsToFreqRatioUnlimited(modLfo);
226    
227     return modEg * modLfo;
228 iliev 2205 }
229    
230     float EndpointUnit::GetPitch() {
231 iliev 2207 double modEg, modLfo, vibLfo;
232     modEg = prmModEgPitch->pUnit->Active() ? RTMath::CentsToFreqRatioUnlimited(prmModEgPitch->GetValue()) : 1;
233     modLfo = prmModLfoPitch->pUnit->Active() ? RTMath::CentsToFreqRatioUnlimited(prmModLfoPitch->GetValue()) : 1;
234     vibLfo = prmVibLfo->pUnit->Active() ? RTMath::CentsToFreqRatioUnlimited(prmVibLfo->GetValue()) : 1;
235 iliev 2205
236 iliev 2207 return modEg * modLfo * vibLfo;
237 iliev 2205 }
238    
239     float EndpointUnit::GetResonance() {
240     return 1;
241     }
242    
243     SF2SignalUnitRack::SF2SignalUnitRack(Voice* pVoice): SignalUnitRackBase<Voice>(pVoice) {
244     Units.add(&suVolEG);
245     Units.add(&suModEG);
246 iliev 2207 Units.add(&suModLfo);
247 iliev 2205 Units.add(&suVibLfo);
248     Units.add(&suEndpoint);
249    
250     // Volume envelope
251 iliev 2207 suEndpoint.Params.add(SignalUnit::Parameter(&suVolEG)); // Volume
252 iliev 2205 // Modulation envelope
253 iliev 2207 suEndpoint.Params.add(SignalUnit::Parameter(&suModEG)); // Pitch
254     suEndpoint.Params.add(SignalUnit::Parameter(&suModEG)); // Filter cutoff
255     // Modulation LFO
256     suEndpoint.Params.add(SignalUnit::Parameter(&suModLfo)); // Volume
257     suEndpoint.Params.add(SignalUnit::Parameter(&suModLfo)); // Pitch
258     suEndpoint.Params.add(SignalUnit::Parameter(&suModLfo)); // Filter cutoff
259 iliev 2205 // Vibrato LFO
260 iliev 2207 suEndpoint.Params.add(SignalUnit::Parameter(&suVibLfo)); // Pitch
261    
262     /* This should be done at the end because when a parameter is added to
263     ArrayList a new copy is made for all parameters */
264     suEndpoint.prmVolEg = &suEndpoint.Params[0];
265     suEndpoint.prmModEgPitch = &suEndpoint.Params[1];
266     suEndpoint.prmModEgCutoff = &suEndpoint.Params[2];
267     suEndpoint.prmModLfoVol = &suEndpoint.Params[3];
268     suEndpoint.prmModLfoPitch = &suEndpoint.Params[4];
269     suEndpoint.prmModLfoCutoff = &suEndpoint.Params[5];
270     suEndpoint.prmVibLfo = &suEndpoint.Params[6];
271 iliev 2205 }
272    
273     void SF2SignalUnitRack::Trigger() {
274     // The region settings are available after the voice is triggered
275    
276     SignalUnitRackBase<Voice>::Trigger();
277     }
278    
279     EndpointSignalUnit* SF2SignalUnitRack::GetEndpointUnit() {
280     return static_cast<EndpointSignalUnit*> (&suEndpoint);
281     }
282    
283     }} // namespace LinuxSampler::sf2

  ViewVC Help
Powered by ViewVC