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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2220 - (show annotations) (download)
Thu Jul 28 15:47:51 2011 UTC (12 years, 8 months ago) by iliev
File size: 11244 byte(s)
* sfz engine: implemented opcodes ampeg_delay, ampeg_vel2delay
  pitcheg_delay, pitcheg_start, pitcheg_attack, pitcheg_hold,
  pitcheg_decay, pitcheg_sustain, pitcheg_release, pitcheg_vel2delay,
  pitcheg_vel2attack, pitcheg_vel2hold, pitcheg_vel2decay,
  pitcheg_vel2sustain, pitcheg_vel2release, pitcheg_depth

1 /***************************************************************************
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 "SfzSignalUnitRack.h"
24 #include "Voice.h"
25
26 namespace LinuxSampler { namespace sfz {
27
28 SfzSignalUnit::SfzSignalUnit(SfzSignalUnitRack* rack): SignalUnit(rack), pVoice(rack->pVoice) {
29
30 }
31
32 double SfzSignalUnit::GetSampleRate() {
33 return pVoice->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
34 }
35
36
37 void EGv1Unit::Trigger() {
38 ::sfz::Region* const pRegion = pVoice->pRegion;
39
40 // the length of the decay and release curves are dependent on the velocity
41 const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity);
42
43 // set the delay trigger
44 uiDelayTrigger = (pRegion->ampeg_delay + pRegion->ampeg_vel2delay * velrelease) * GetSampleRate();
45
46 EG.trigger(uint(pRegion->ampeg_start * 10),
47 std::max(0.0, pRegion->ampeg_attack + pRegion->ampeg_vel2attack * velrelease),
48 std::max(0.0, pRegion->ampeg_hold + pRegion->ampeg_vel2hold * velrelease),
49 std::max(0.0, pRegion->ampeg_decay + pRegion->ampeg_vel2decay * velrelease),
50 uint(std::min(std::max(0.0, 10 * (pRegion->ampeg_sustain + pRegion->ampeg_vel2sustain * velrelease)), 1000.0)),
51 std::max(0.0, pRegion->ampeg_release + pRegion->ampeg_vel2release * velrelease),
52 GetSampleRate());
53 }
54
55
56 void EGv2Unit::Trigger() {
57 EG.trigger(*pEGInfo, GetSampleRate(), pVoice->MIDIVelocity);
58 }
59
60
61 void PitchEGUnit::Trigger() {
62 ::sfz::Region* const pRegion = pVoice->pRegion;
63 depth = pRegion->pitcheg_depth;
64
65 // the length of the decay and release curves are dependent on the velocity
66 const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity);
67
68 // set the delay trigger
69 uiDelayTrigger = (pRegion->pitcheg_delay + pRegion->pitcheg_vel2delay * velrelease) * GetSampleRate();
70
71 EG.trigger(uint(pRegion->pitcheg_start * 10),
72 std::max(0.0, pRegion->pitcheg_attack + pRegion->pitcheg_vel2attack * velrelease),
73 std::max(0.0, pRegion->pitcheg_hold + pRegion->pitcheg_vel2hold * velrelease),
74 std::max(0.0, pRegion->pitcheg_decay + pRegion->pitcheg_vel2decay * velrelease),
75 uint(std::min(std::max(0.0, 10 * (pRegion->pitcheg_sustain + pRegion->pitcheg_vel2sustain * velrelease)), 1000.0)),
76 std::max(0.0, pRegion->pitcheg_release + pRegion->pitcheg_vel2release * velrelease),
77 GetSampleRate());
78 }
79
80
81 void LFOUnit::Increment() {
82 if (DelayStage()) return;
83
84 SignalUnit::Increment();
85
86 Level = lfo.render();
87 }
88
89 void LFOUnit::Trigger() {
90 //reset
91 Level = 0;
92
93 // set the delay trigger
94 uiDelayTrigger = pLfoInfo->delay * GetSampleRate();
95 }
96
97 void LFOv2Unit::Trigger() {
98 LFOUnit::Trigger();
99
100 lfo.trigger (
101 pLfoInfo->freq,
102 start_level_mid,
103 1, 0, false, GetSampleRate()
104 );
105 lfo.update(0);
106 }
107
108
109 EndpointUnit::EndpointUnit(SfzSignalUnitRack* rack): EndpointSignalUnit(rack) {
110
111 }
112
113 SfzSignalUnitRack* const EndpointUnit::GetRack() {
114 return static_cast<SfzSignalUnitRack* const>(pRack);
115 }
116
117 void EndpointUnit::Trigger() {
118
119 }
120
121 bool EndpointUnit::Active() {
122 if (GetRack()->suVolEG.Active()) return true;
123
124 bool b = false;
125 for (int i = 0; i < GetRack()->volEGs.size(); i++) {
126 if (GetRack()->volEGs[i]->Active()) { b = true; break; }
127 }
128
129 return b;
130 }
131
132 float EndpointUnit::GetVolume() {
133 float vol = GetRack()->suVolEG.Active() ? GetRack()->suVolEG.GetLevel() : 0;
134
135 for (int i = 0; i < GetRack()->volEGs.size(); i++) {
136 EGv2Unit* eg = GetRack()->volEGs[i];
137 if (!eg->Active()) continue;
138 vol += eg->GetLevel() * (eg->pEGInfo->amplitude / 100.0f);
139 }
140
141 return vol;
142 }
143
144 float EndpointUnit::GetFilterCutoff() {
145 float val = 1;
146
147 for (int i = 0; i < GetRack()->filLFOs.size(); i++) {
148 LFOv2Unit* lfo = GetRack()->filLFOs[i];
149 if (!lfo->Active()) continue;
150
151 float f = lfo->GetLevel() * lfo->pLfoInfo->cutoff;
152 val *= RTMath::CentsToFreqRatioUnlimited(f);
153 }
154
155 return val;
156 }
157
158 float EndpointUnit::GetPitch() {
159 EGv1Unit* u = &(GetRack()->suPitchEG);
160 double pitchEg = u->Active() ? RTMath::CentsToFreqRatioUnlimited(u->GetLevel() * u->depth) : 1;
161 return pitchEg;
162 }
163
164 float EndpointUnit::GetResonance() {
165 float val = 0;
166
167 for (int i = 0; i < GetRack()->resLFOs.size(); i++) {
168 LFOv2Unit* lfo = GetRack()->resLFOs[i];
169 if (!lfo->Active()) continue;
170
171 val += lfo->GetLevel() * lfo->pLfoInfo->resonance;
172 }
173
174 return val;
175 }
176
177 float EndpointUnit::GetPan() {
178 float pan = 0;
179
180 for (int i = 0; i < GetRack()->panLFOs.size(); i++) {
181 LFOv2Unit* lfo = GetRack()->panLFOs[i];
182 if (!lfo->Active()) continue;
183
184 pan += lfo->GetLevel() * lfo->pLfoInfo->pan;
185 }
186
187 if(pan < -100) return -100;
188 if(pan > 100) return 100;
189
190 return pan;
191 }
192
193
194 SfzSignalUnitRack::SfzSignalUnitRack(Voice* voice)
195 : SignalUnitRack(MaxUnitCount), pVoice(voice), suEndpoint(this), suVolEG(this), suPitchEG(this),
196 EGs(maxEgCount), volEGs(maxEgCount), pitchEGs(maxEgCount),
197 LFOs(maxLfoCount), filLFOs(maxLfoCount), resLFOs(maxLfoCount), panLFOs(maxLfoCount)
198 {
199 suEndpoint.pVoice = suVolEG.pVoice = suPitchEG.pVoice = voice;
200
201 for (int i = 0; i < EGs.capacity(); i++) {
202 EGs[i] = new EGv2Unit(this);
203 EGs[i]->pVoice = voice;
204 }
205
206 for (int i = 0; i < LFOs.capacity(); i++) {
207 LFOs[i] = new LFOv2Unit(this);
208 LFOs[i]->pVoice = voice;
209 }
210 }
211
212 SfzSignalUnitRack::~SfzSignalUnitRack() {
213 for (int i = 0; i < EGs.capacity(); i++) {
214 delete EGs[i]; EGs[i] = NULL;
215 }
216
217 for (int i = 0; i < LFOs.capacity(); i++) {
218 delete LFOs[i]; LFOs[i] = NULL;
219 }
220 }
221
222 void SfzSignalUnitRack::Trigger() {
223 EGs.clear();
224 volEGs.clear();
225 pitchEGs.clear();
226
227 LFOs.clear();
228 filLFOs.clear();
229 resLFOs.clear();
230 panLFOs.clear();
231
232 ::sfz::Region* const pRegion = pVoice->pRegion;
233
234 for (int i = 0; i < pRegion->eg.size(); i++) {
235 if (pRegion->eg[i].node.size() == 0) continue;
236
237 if(EGs.size() < EGs.capacity()) {
238 EGv2Unit eg(this);
239 eg.pEGInfo = &(pRegion->eg[i]);
240 EGs.increment()->Copy(eg);
241 } else { std::cerr << "Maximum number of EGs reached!" << std::endl; break; }
242
243 if (pRegion->eg[i].amplitude > 0) {
244 if(volEGs.size() < volEGs.capacity()) volEGs.add(EGs[EGs.size() - 1]);
245 else std::cerr << "Maximum number of EGs reached!" << std::endl;
246 }
247 }
248
249 if (pRegion->ampeg_sustain == -1) {
250 if (volEGs.size() > 0) pRegion->ampeg_sustain = 0;
251 else pRegion->ampeg_sustain = 100;
252 }
253
254 // LFO
255 for (int i = 0; i < pRegion->lfos.size(); i++) {
256 if (pRegion->lfos[i].freq == -1) continue; // Not initialized
257
258 if(LFOs.size() < LFOs.capacity()) {
259 LFOv2Unit lfo(this);
260 lfo.pLfoInfo = &(pRegion->lfos[i]);
261 LFOs.increment()->Copy(lfo);
262 } else { std::cerr << "Maximum number of LFOs reached!" << std::endl; break; }
263
264 if (pRegion->lfos[i].cutoff != 0) {
265 if(filLFOs.size() < filLFOs.capacity()) filLFOs.add(LFOs[LFOs.size() - 1]);
266 else std::cerr << "Maximum number of LFOs reached!" << std::endl;
267 }
268
269 if (pRegion->lfos[i].resonance != 0) {
270 if(resLFOs.size() < resLFOs.capacity()) resLFOs.add(LFOs[LFOs.size() - 1]);
271 else std::cerr << "Maximum number of LFOs reached!" << std::endl;
272 }
273
274 if (pRegion->lfos[i].pan != 0) {
275 if(panLFOs.size() < panLFOs.capacity()) panLFOs.add(LFOs[LFOs.size() - 1]);
276 else std::cerr << "Maximum number of LFOs reached!" << std::endl;
277 }
278 }
279
280 Units.clear();
281
282 Units.add(&suVolEG);
283 Units.add(&suPitchEG);
284
285 for (int i = 0; i < EGs.size(); i++) {
286 Units.add(EGs[i]);
287 }
288
289 for (int i = 0; i < LFOs.size(); i++) {
290 Units.add(LFOs[i]);
291 }
292
293 Units.add(&suEndpoint);
294
295 SignalUnitRack::Trigger();
296 }
297
298 EndpointSignalUnit* SfzSignalUnitRack::GetEndpointUnit() {
299 return &suEndpoint;
300 }
301
302 void SfzSignalUnitRack::EnterFadeOutStage() {
303 suVolEG.EG.enterFadeOutStage();
304
305 for (int i = 0; i < volEGs.size(); i++) {
306 volEGs[i]->EG.enterFadeOutStage();
307 }
308 }
309
310 }} // namespace LinuxSampler::sfz

  ViewVC Help
Powered by ViewVC