2 ZynAddSubFX - a software synthesizer
4 Envelope.cpp - Envelope implementation
5 Copyright (C) 2002-2005 Nasca Octavian Paul
6 Author: Nasca Octavian Paul
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
16 #include "../Params/EnvelopeParams.h"
20 Envelope::Envelope(EnvelopeParams
&pars
, float basefreq
, float bufferdt
,
21 WatchManager
*m
, const char *watch_prefix
)
22 :watchOut(m
, watch_prefix
, "out")
24 envpoints
= pars
.Penvpoints
;
25 if(envpoints
> MAX_ENVELOPE_POINTS
)
26 envpoints
= MAX_ENVELOPE_POINTS
;
27 envsustain
= (pars
.Penvsustain
== 0) ? -1 : pars
.Penvsustain
;
28 forcedrelease
= pars
.Pforcedrelease
;
29 envstretch
= powf(440.0f
/ basefreq
, pars
.Penvstretch
/ 64.0f
);
30 linearenvelope
= pars
.Plinearenvelope
;
37 //for amplitude envelopes
38 if((mode
== 1) && !linearenvelope
)
39 mode
= 2; //change to log envelope
40 if((mode
== 2) && linearenvelope
)
41 mode
= 1; //change to linear
43 for(int i
= 0; i
< MAX_ENVELOPE_POINTS
; ++i
) {
44 const float tmp
= pars
.getdt(i
) * envstretch
;
46 envdt
[i
] = bufferdt
/ tmp
;
48 envdt
[i
] = 2.0f
; //any value larger than 1
52 envval
[i
] = (1.0f
- pars
.Penvval
[i
] / 127.0f
) * -40;
57 * fabsf(pars
.Penvval
[i
]
58 - 64.0f
) / 64.0f
) - 1.0f
) * 100.0f
;
59 if(pars
.Penvval
[i
] < 64)
60 envval
[i
] = -envval
[i
];
63 envval
[i
] = (pars
.Penvval
[i
] - 64.0f
) / 64.0f
* 6.0f
; //6 octaves (filtru)
66 envval
[i
] = (pars
.Penvval
[i
] - 64.0f
) / 64.0f
* 10;
69 envval
[i
] = pars
.Penvval
[i
] / 127.0f
;
75 currentpoint
= 1; //the envelope starts from 1
88 * Release the key (note envelope)
90 void Envelope::releasekey()
99 void Envelope::forceFinish(void)
104 void Envelope::watch(float time
, float value
)
112 pos
[1] = 1 - value
/ -40.f
;
116 factor1
= log(value
/100. + 1.) / (6. * log(2));
117 factor2
= log(1. - value
/100.) / (6. * log(2));
118 pos
[1] = ((0.5 * factor1
) >= 0) ? (0.5 * factor1
+ 0.5) : (0.5 - factor2
* 0.5);
122 pos
[1] = (value
+ 6.) / 12.f
;
126 pos
[1] = (value
+ 10.) / 20.f
;
138 float Envelope::envout(bool doWatch
)
141 if(envfinish
) { //if the envelope is finished
142 envoutval
= envval
[envpoints
- 1];
144 watch(envpoints
- 1, envoutval
);
148 if((currentpoint
== envsustain
+ 1) && !keyreleased
) { //if it is sustaining now
149 envoutval
= envval
[envsustain
];
151 watch(envsustain
, envoutval
);
156 if(keyreleased
&& forcedrelease
) { //do the forced release
157 int tmp
= (envsustain
< 0) ? (envpoints
- 1) : (envsustain
+ 1); //if there is no sustain point, use the last point for release
159 if(envdt
[tmp
] < 0.00000001f
)
162 out
= envoutval
+ (envval
[tmp
] - envoutval
) * t
;
164 t
+= envdt
[tmp
] * envstretch
;
166 if(t
>= 1.0f
) { // move to the next segment
167 currentpoint
= envsustain
+ 2;
170 inct
= envdt
[currentpoint
];
171 if((currentpoint
>= envpoints
) || (envsustain
< 0))
176 watch(tmp
+ t
, envoutval
);
182 out
= envval
[currentpoint
];
184 out
= envval
[currentpoint
- 1]
185 + (envval
[currentpoint
] - envval
[currentpoint
- 1]) * t
;
190 if(currentpoint
>= envpoints
- 1)
195 inct
= envdt
[currentpoint
];
201 watch(currentpoint
+ t
, envoutval
);
207 * Envelope Output (dB)
209 float Envelope::envout_dB()
215 if((currentpoint
== 1) && (!keyreleased
|| !forcedrelease
)) { //first point is always lineary interpolated <- seems to have odd effects
216 float v1
= EnvelopeParams::env_dB2rap(envval
[0]);
217 float v2
= EnvelopeParams::env_dB2rap(envval
[1]);
218 out
= v1
+ (v2
- v1
) * t
;
230 envoutval
= EnvelopeParams::env_rap2dB(out
);
232 envoutval
= MIN_ENVELOPE_DB
;
237 watch(currentpoint
+ t
, out
);
238 return EnvelopeParams::env_dB2rap(out
);
242 bool Envelope::finished() const