/[svn]/linuxsampler/trunk/src/engines/gig/EGADSR.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/gig/EGADSR.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3034 - (show annotations) (download)
Mon Oct 31 00:05:00 2016 UTC (7 years, 5 months ago) by schoenebeck
File size: 12110 byte(s)
* Fixed a bunch of minor issues (mostly compiler warnings).
* Bumped version (2.0.0.svn31).

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2016 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include "EGADSR.h"
25
26 #include "../../common/global_private.h"
27
28 namespace LinuxSampler { namespace gig {
29
30 void EGADSR::update(event_t Event, uint SampleRate) {
31 if (atEnd(Event)) return;
32
33 if (Event == event_hold_end) HoldAttack = false;
34
35 switch (Stage) {
36 case stage_attack:
37 switch (Event) {
38 case event_release:
39 enterReleasePart1Stage();
40 break;
41 case event_stage_end:
42 if (HoldAttack)
43 enterAttackHoldStage();
44 else
45 enterDecay1Part1Stage(SampleRate);
46 break;
47 default: ; // noop
48 }
49 break;
50 case stage_attack_hold:
51 switch (Event) {
52 case event_stage_end: {// just refresh time
53 const int intMax = (unsigned int) -1 >> 1;
54 StepsLeft = intMax; // we use the highest possible value
55 break;
56 }
57 case event_hold_end:
58 enterDecay1Part1Stage(SampleRate);
59 break;
60 case event_release:
61 enterReleasePart1Stage();
62 break;
63 default: ; // noop
64 }
65 break;
66 case stage_decay1_part1:
67 switch (Event) {
68 case event_stage_end:
69 enterDecay1Part2Stage(SampleRate);
70 break;
71 case event_release:
72 enterReleasePart1Stage();
73 break;
74 default: ; // noop
75 }
76 break;
77 case stage_decay1_part2:
78 switch (Event) {
79 case event_release:
80 enterReleasePart1Stage();
81 break;
82 case event_stage_end:
83 if (Level < CONFIG_EG_BOTTOM)
84 enterEndStage();
85 else if (InfiniteSustain)
86 enterSustainStage();
87 else
88 enterDecay2Stage(SampleRate);
89 break;
90 default: ; // noop
91 }
92 break;
93 case stage_decay2:
94 switch (Event) {
95 case event_stage_end:
96 enterFadeOutStage();
97 break;
98 case event_release:
99 enterReleasePart1Stage();
100 break;
101 case event_hold_end:
102 enterDecay1Part1Stage(SampleRate);
103 break;
104 default: ; // noop
105 }
106 break;
107 case stage_sustain:
108 switch (Event) {
109 case event_stage_end: {// just refresh time
110 const int intMax = (unsigned int) -1 >> 1;
111 StepsLeft = intMax; // we use the highest possible value
112 break;
113 }
114 case event_release:
115 enterReleasePart1Stage();
116 break;
117 case event_hold_end:
118 enterDecay1Part1Stage(SampleRate);
119 break;
120 default: ; // noop
121 }
122 break;
123 case stage_release_part1:
124 switch (Event) {
125 case event_stage_end:
126 enterReleasePart2Stage();
127 break;
128 case event_cancel_release:
129 if (InfiniteSustain)
130 enterSustainStage();
131 else
132 enterDecay2Stage(SampleRate);
133 break;
134 default: ; // noop
135 }
136 break;
137 case stage_release_part2:
138 switch (Event) {
139 case event_stage_end:
140 enterFadeOutStage();
141 break;
142 case event_cancel_release:
143 if (InfiniteSustain)
144 enterSustainStage();
145 else
146 enterDecay2Stage(SampleRate);
147 break;
148 default: ; // noop
149 }
150 break;
151 case stage_fadeout:
152 case stage_end:
153 ; // noop
154 }
155 }
156
157 void EGADSR::trigger(uint PreAttack, float AttackTime, bool HoldAttack, float Decay1Time, double Decay2Time, bool InfiniteSustain, uint SustainLevel, float ReleaseTime, float Volume, uint SampleRate) {
158 this->SustainLevel = SustainLevel / 1000.0;
159 this->InfiniteSustain = InfiniteSustain;
160 this->HoldAttack = HoldAttack;
161
162 this->Decay1Time = Decay1Time;
163 this->Decay2Time = Decay2Time;
164
165 invVolume = 1 / Volume;
166 ExpOffset = (0.25 - 1 / 3.55) * invVolume;
167
168 // calculate release stage parameters (lin+exp curve)
169 if (ReleaseTime < CONFIG_EG_MIN_RELEASE_TIME) ReleaseTime = CONFIG_EG_MIN_RELEASE_TIME; // to avoid click sounds at the end of the sample playback
170 const float ReleaseStepsLeft = (long) (ReleaseTime * SampleRate);
171 ReleaseSlope = 1.365 * (0 - 1) / ReleaseStepsLeft;
172 ReleaseCoeff = ReleaseSlope * invVolume;
173 ReleaseSlope *= 3.55;
174 ReleaseCoeff2 = exp(ReleaseSlope);
175 ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);
176 ReleaseLevel2 = 0.25 * invVolume;
177
178 enterFirstStage();
179 enterAttackStage(PreAttack, AttackTime, SampleRate);
180 }
181
182 void EGADSR::enterAttackStage(const uint PreAttack, const float AttackTime, const uint SampleRate) {
183 Stage = stage_attack;
184 Segment = segment_lin;
185
186 if (AttackTime >= 1e-8) {
187 // Measurements of GSt output shows that the real attack time
188 // is about 65.5% of the value specified in the gig file.
189 // The minimum attack value used is 0.0316.
190 StepsLeft = int(0.655f * RTMath::Max(AttackTime, 0.0316f) * SampleRate);
191 Level = (float) PreAttack / 1000.0;
192 Coeff = 0.896f * (1.0f - Level) / StepsLeft; // max level is a bit lower if attack != 0
193 } else { // attack is zero - immediately jump to the next stage
194 Level = 1.029f; // a bit higher than max sustain
195 if (HoldAttack) enterAttackHoldStage();
196 else enterDecay1Part1Stage(SampleRate);
197 }
198 }
199
200 void EGADSR::enterAttackHoldStage() {
201 Stage = stage_attack_hold;
202 Segment = segment_lin;
203 Coeff = 0.0f; // don't rise anymore
204 const int intMax = (unsigned int) -1 >> 1;
205 StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
206 }
207
208 void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
209 // The decay1 and release stage both consist of two parts,
210 // first a linear curve, f, followed by an exponential curve,
211 // g:
212 //
213 // f(x + d) = f(x) + Coeff
214 // g(x + d) = Coeff2 * g(x) + Coeff3
215 //
216 // (where d is 1/SampleRate). The transition from f to g is
217 // done when f(x) has reached Level2 = 25% of full volume.
218 StepsLeft = (int) (Decay1Time * SampleRate);
219 if (StepsLeft && Level > SustainLevel) {
220 Stage = stage_decay1_part1;
221 Segment = segment_lin;
222 Decay1Slope = (1.347f * SustainLevel - 1.361f) / StepsLeft;
223 Coeff = Decay1Slope * invVolume;
224 Decay1Level2 = 0.25 * invVolume;
225 StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
226 if (StepsLeft <= 0) enterDecay1Part2Stage(SampleRate);
227 } else {
228 if (InfiniteSustain) enterSustainStage();
229 else enterDecay2Stage(SampleRate);
230 }
231 }
232
233 void EGADSR::enterDecay1Part2Stage(const uint SampleRate) {
234 if (SustainLevel < Decay1Level2) {
235 Stage = stage_decay1_part2;
236 Segment = segment_exp;
237 Decay1Slope *= 3.55;
238 Coeff = exp(Decay1Slope);
239 Offset = ExpOffset * (1 - Coeff);
240 StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);
241 if (StepsLeft > 0) return;
242 }
243 if (InfiniteSustain) enterSustainStage();
244 else enterDecay2Stage(SampleRate);
245 }
246
247 void EGADSR::enterDecay2Stage(const uint SampleRate) {
248 Stage = stage_decay2;
249 Segment = segment_lin;
250 Decay2Time = RTMath::Max(Decay2Time, 0.05f);
251 StepsLeft = (int) (Decay2Time * SampleRate);
252 Coeff = (-1.03 / StepsLeft) * invVolume;
253 //FIXME: do we really have to calculate 'StepsLeft' two times?
254 StepsLeft = int((CONFIG_EG_BOTTOM - Level) / Coeff);
255 if (StepsLeft <= 0) enterEndStage();
256 }
257
258 void EGADSR::enterSustainStage() {
259 Stage = stage_sustain;
260 Segment = segment_lin;
261 Coeff = 0.0f; // don't change the envelope level in this stage
262 const int intMax = (unsigned int) -1 >> 1;
263 StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
264 }
265
266 void EGADSR::enterReleasePart1Stage() {
267 Stage = stage_release_part1;
268 Segment = segment_lin;
269 StepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
270 Coeff = ReleaseCoeff;
271 if (StepsLeft <= 0) enterReleasePart2Stage();
272 }
273
274 void EGADSR::enterReleasePart2Stage() {
275 Stage = stage_release_part2;
276 Segment = segment_exp;
277 StepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);
278 Coeff = ReleaseCoeff2;
279 Offset = ReleaseCoeff3;
280 if (StepsLeft <= 0) enterFadeOutStage();
281 }
282
283 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC