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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3561 - (show annotations) (download)
Fri Aug 23 11:44:00 2019 UTC (4 years, 8 months ago) by schoenebeck
File size: 11660 byte(s)
NKSP: Added standard units support for numbers and final "!" operator:

* NKSP strictness: Variable names, function names and preprocessor condition
  names must start with a regular character (a-z or A-Z); starting them with
  a digit or underscore is no longer allowed.

* NKSP parser fix: equal comparison operator "=" and not equal comparison
  operator "#" must only accept integer operands.

* NKSP language: Implemented support for standard units like Hertz, seconds,
  Bel including support for metric unit prefixes; so one can now e.g.
  conveniently use numbers in scripts like "5us" meaning "5 microseconds",
  or e.g. "12kHz" meaning "12 kilo Hertz", or e.g. "-14mdB" meaning
  "minus 14 Millidecibel", or e.g. "28c" meaning "28 cents" (for tuning).

* NKSP language: Introduced "final" operator "!" which is specifically
  intended for synthesis parameter values to denote that the synthesis
  parameter value is intended to be the "final" value for that synthesis
  parameter that should explicitly be used by the engine and thus causing
  the sampler engine to ignore all other modulation sources for the same
  synthesis parameter (like e.g. LFO, EG); by simply prefixing a value,
  variable or formula with this new "!" operator the expression is marked as
  being "final".

* Bumped version (2.1.1.svn4).

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

  ViewVC Help
Powered by ViewVC