/[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 2408 - (show annotations) (download)
Sat Feb 2 08:22:49 2013 UTC (7 years, 11 months ago) by persson
File size: 11712 byte(s)
* gig engine: fixed EG1 modulation when attack or release is zero

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2013 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 }
48 break;
49 case stage_attack_hold:
50 switch (Event) {
51 case event_stage_end: {// just refresh time
52 const int intMax = (unsigned int) -1 >> 1;
53 StepsLeft = intMax; // we use the highest possible value
54 break;
55 }
56 case event_hold_end:
57 enterDecay1Part1Stage(SampleRate);
58 break;
59 case event_release:
60 enterReleasePart1Stage();
61 break;
62 }
63 break;
64 case stage_decay1_part1:
65 switch (Event) {
66 case event_stage_end:
67 enterDecay1Part2Stage(SampleRate);
68 break;
69 case event_release:
70 enterReleasePart1Stage();
71 break;
72 }
73 break;
74 case stage_decay1_part2:
75 switch (Event) {
76 case event_release:
77 enterReleasePart1Stage();
78 break;
79 case event_stage_end:
80 if (Level < CONFIG_EG_BOTTOM)
81 enterEndStage();
82 else if (InfiniteSustain)
83 enterSustainStage();
84 else
85 enterDecay2Stage(SampleRate);
86 break;
87 }
88 break;
89 case stage_decay2:
90 switch (Event) {
91 case event_stage_end:
92 enterFadeOutStage();
93 break;
94 case event_release:
95 enterReleasePart1Stage();
96 break;
97 case event_hold_end:
98 enterDecay1Part1Stage(SampleRate);
99 break;
100 }
101 break;
102 case stage_sustain:
103 switch (Event) {
104 case event_stage_end: {// just refresh time
105 const int intMax = (unsigned int) -1 >> 1;
106 StepsLeft = intMax; // we use the highest possible value
107 break;
108 }
109 case event_release:
110 enterReleasePart1Stage();
111 break;
112 case event_hold_end:
113 enterDecay1Part1Stage(SampleRate);
114 break;
115 }
116 break;
117 case stage_release_part1:
118 switch (Event) {
119 case event_stage_end:
120 enterReleasePart2Stage();
121 break;
122 case event_cancel_release:
123 if (InfiniteSustain)
124 enterSustainStage();
125 else
126 enterDecay2Stage(SampleRate);
127 break;
128 }
129 break;
130 case stage_release_part2:
131 switch (Event) {
132 case event_stage_end:
133 enterFadeOutStage();
134 break;
135 case event_cancel_release:
136 if (InfiniteSustain)
137 enterSustainStage();
138 else
139 enterDecay2Stage(SampleRate);
140 break;
141 }
142 break;
143 }
144 }
145
146 void EGADSR::trigger(uint PreAttack, float AttackTime, bool HoldAttack, float Decay1Time, double Decay2Time, bool InfiniteSustain, uint SustainLevel, float ReleaseTime, float Volume, uint SampleRate) {
147 this->SustainLevel = SustainLevel / 1000.0;
148 this->InfiniteSustain = InfiniteSustain;
149 this->HoldAttack = HoldAttack;
150
151 this->Decay1Time = Decay1Time;
152 this->Decay2Time = Decay2Time;
153
154 invVolume = 1 / Volume;
155 ExpOffset = (0.25 - 1 / 3.55) * invVolume;
156
157 // calculate release stage parameters (lin+exp curve)
158 if (ReleaseTime < CONFIG_EG_MIN_RELEASE_TIME) ReleaseTime = CONFIG_EG_MIN_RELEASE_TIME; // to avoid click sounds at the end of the sample playback
159 const float ReleaseStepsLeft = (long) (ReleaseTime * SampleRate);
160 ReleaseSlope = 1.365 * (0 - 1) / ReleaseStepsLeft;
161 ReleaseCoeff = ReleaseSlope * invVolume;
162 ReleaseSlope *= 3.55;
163 ReleaseCoeff2 = exp(ReleaseSlope);
164 ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);
165 ReleaseLevel2 = 0.25 * invVolume;
166
167 enterFirstStage();
168 enterAttackStage(PreAttack, AttackTime, SampleRate);
169 }
170
171 void EGADSR::enterAttackStage(const uint PreAttack, const float AttackTime, const uint SampleRate) {
172 Stage = stage_attack;
173 Segment = segment_lin;
174
175 if (AttackTime >= 1e-8) {
176 // Measurements of GSt output shows that the real attack time
177 // is about 65.5% of the value specified in the gig file.
178 // The minimum attack value used is 0.0316.
179 StepsLeft = int(0.655f * RTMath::Max(AttackTime, 0.0316f) * SampleRate);
180 Level = (float) PreAttack / 1000.0;
181 Coeff = 0.896f * (1.0f - Level) / StepsLeft; // max level is a bit lower if attack != 0
182 } else { // attack is zero - immediately jump to the next stage
183 Level = 1.029f; // a bit higher than max sustain
184 if (HoldAttack) enterAttackHoldStage();
185 else enterDecay1Part1Stage(SampleRate);
186 }
187 }
188
189 void EGADSR::enterAttackHoldStage() {
190 Stage = stage_attack_hold;
191 Segment = segment_lin;
192 Coeff = 0.0f; // don't rise anymore
193 const int intMax = (unsigned int) -1 >> 1;
194 StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
195 }
196
197 void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
198 // The decay1 and release stage both consist of two parts,
199 // first a linear curve, f, followed by an exponential curve,
200 // g:
201 //
202 // f(x + d) = f(x) + Coeff
203 // g(x + d) = Coeff2 * g(x) + Coeff3
204 //
205 // (where d is 1/SampleRate). The transition from f to g is
206 // done when f(x) has reached Level2 = 25% of full volume.
207 StepsLeft = (int) (Decay1Time * SampleRate);
208 if (StepsLeft && Level > SustainLevel) {
209 Stage = stage_decay1_part1;
210 Segment = segment_lin;
211 Decay1Slope = (1.347f * SustainLevel - 1.361f) / StepsLeft;
212 Coeff = Decay1Slope * invVolume;
213 Decay1Level2 = 0.25 * invVolume;
214 StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
215 if (StepsLeft <= 0) enterDecay1Part2Stage(SampleRate);
216 } else {
217 if (InfiniteSustain) enterSustainStage();
218 else enterDecay2Stage(SampleRate);
219 }
220 }
221
222 void EGADSR::enterDecay1Part2Stage(const uint SampleRate) {
223 if (SustainLevel < Decay1Level2) {
224 Stage = stage_decay1_part2;
225 Segment = segment_exp;
226 Decay1Slope *= 3.55;
227 Coeff = exp(Decay1Slope);
228 Offset = ExpOffset * (1 - Coeff);
229 StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);
230 if (StepsLeft > 0) return;
231 }
232 if (InfiniteSustain) enterSustainStage();
233 else enterDecay2Stage(SampleRate);
234 }
235
236 void EGADSR::enterDecay2Stage(const uint SampleRate) {
237 Stage = stage_decay2;
238 Segment = segment_lin;
239 Decay2Time = RTMath::Max(Decay2Time, 0.05f);
240 StepsLeft = (int) (Decay2Time * SampleRate);
241 Coeff = (-1.03 / StepsLeft) * invVolume;
242 //FIXME: do we really have to calculate 'StepsLeft' two times?
243 StepsLeft = int((CONFIG_EG_BOTTOM - Level) / Coeff);
244 if (StepsLeft <= 0) enterEndStage();
245 }
246
247 void EGADSR::enterSustainStage() {
248 Stage = stage_sustain;
249 Segment = segment_lin;
250 Coeff = 0.0f; // don't change the envelope level in this stage
251 const int intMax = (unsigned int) -1 >> 1;
252 StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
253 }
254
255 void EGADSR::enterReleasePart1Stage() {
256 Stage = stage_release_part1;
257 Segment = segment_lin;
258 StepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
259 Coeff = ReleaseCoeff;
260 if (StepsLeft <= 0) enterReleasePart2Stage();
261 }
262
263 void EGADSR::enterReleasePart2Stage() {
264 Stage = stage_release_part2;
265 Segment = segment_exp;
266 StepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);
267 Coeff = ReleaseCoeff2;
268 Offset = ReleaseCoeff3;
269 if (StepsLeft <= 0) enterFadeOutStage();
270 }
271
272 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC