Dear devs,<br><br>After a bug in Envelope was found I tried my hand at fixing it which brought yet more issues to the surface.<br><br>I also tried to fix those but I'm not sure what this might now break so I'm out of my depth.
<br><br>Details and code are here;<br><a href="http://electro-music.com/forum/viewtopic.php?p=142167#142167">http://electro-music.com/forum/viewtopic.php?p=142167#142167</a><br>Documentation of the various things that went wrong with the official version are above that post.
<br><br>A copy of what I arrived at follows below, I hope this is of some use, if my code isn't I can at least say we now have a clearer image of exactly what the issue is and I had some fun.<br><br>Yours,<br>Kas.<br>
<br>==================================================================<br>/***************************************************/
<br>
/*! \class Envelope
<br>
\brief STK envelope base class.
<br>
<br>
This class implements a simple envelope
<br>
generator which is capable of ramping to
<br>
a target value by a specified \e rate.
<br>
It also responds to simple \e keyOn and
<br>
\e keyOff messages, ramping to 1.0 on
<br>
keyOn and to 0.0 on keyOff.
<br>
<br>
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
<br>
----------------
<br>
This is a experimental "fixed" version by Kassen who doesn't speak C++.
<br>
Don't use this for anything important untill the official devs
<br>
have had a look at it, Don't say I didn't warn you.
<br>
this is a modification on ugen_stk.cpp for chuck <a href="http://1.2.1.0">1.2.1.0</a>,
<br>
which is covered by the GPL (and so so is this).
<br>
<br>
<br>
*/
<br>
/***************************************************/
<br>
<br>
#include <stdio.h>
<br>
<br>
Envelope :: Envelope(void) : Stk()
<br>
{
<br>
target = (MY_FLOAT) 0.0;
<br>
value = (MY_FLOAT) 0.0;
<br>
rate = (MY_FLOAT) 0.001;
<br>
m_target = 1.0;
<br>
m_time = rate * Stk::sampleRate();
<br>
state = 0;
<br>
}
<br>
<br>
Envelope :: ~Envelope(void)
<br>
{
<br>
}
<br>
<br>
void Envelope :: keyOn(void)
<br>
{
<br>
target = (MY_FLOAT) m_target;
<br>
if (value != target) state = 1;
<br>
setTime( m_time );
<br>
}
<br>
<br>
void Envelope :: keyOff(void)
<br>
{
<br>
target = (MY_FLOAT) 0.0;
<br>
if (value != target) state = 1;
<br>
setTime( m_time );
<br>
}
<br>
<br>
void Envelope :: setRate(MY_FLOAT aRate)
<br>
{
<br>
if (aRate < 0.0) {
<br>
printf("[chuck](via Envelope): negative rates not allowed ... correcting!\n");
<br>
rate = -aRate;
<br>
}
<br>
else
<br>
rate = aRate;
<br>
<br>
m_time = (target - value) / (rate * Stk::sampleRate());
<br>
if( m_time < 0.0 ) m_time = -m_time;
<br>
}
<br>
<br>
void Envelope :: setTime(MY_FLOAT aTime)
<br>
{
<br>
if (aTime < 0.0) {
<br>
printf("[chuck](via Envelope): negative times not allowed ... correcting!\n");
<br>
rate = (target -value) / (-aTime * Stk::sampleRate());
<br>
}
<br>
else if( aTime == 0.0 )
<br>
rate = FLT_MAX;
<br>
else
<br>
rate = (target - value) / (aTime * Stk::sampleRate());
<br>
if (rate < 0.0 ) rate = -rate;
<br>
<br>
m_time = aTime;
<br>
if( m_time < 0.0 ) m_time = -m_time;
<br>
}
<br>
<br>
void Envelope :: setTarget(MY_FLOAT aTarget)
<br>
{
<br>
target = m_target = aTarget;
<br>
if (value != target) state = 1;
<br>
<br>
// set time
<br>
setTime( m_time );
<br>
}
<br>
<br>
void Envelope :: setValue(MY_FLOAT aValue)
<br>
{
<br>
state = 0;
<br>
target = aValue;
<br>
value = aValue;
<br>
}
<br>
<br>
int Envelope :: getState(void) const
<br>
{
<br>
return state;
<br>
}
<br>
<br>
MY_FLOAT Envelope :: tick(void)
<br>
{
<br>
if (state) {
<br>
if (target > value) {
<br>
value += rate;
<br>
if (value >= target) {
<br>
value = target;
<br>
state = 0;
<br>
}
<br>
}
<br>
else {
<br>
value -= rate;
<br>
if (value <= target) {
<br>
value = target;
<br>
state = 0;
<br>
}
<br>
}
<br>
}
<br>
return value;
<br>
}
<br>
<br>
MY_FLOAT *Envelope :: tick(MY_FLOAT *vec, unsigned int vectorSize)
<br>
{
<br>
for (unsigned int i=0; i<vectorSize; i++)
<br>
vec[i] = tick();
<br>
<br>
return vec;
<br>
}
<br>
<br>
MY_FLOAT Envelope :: lastOut(void) const
<br>
{
<br>
return value;
<br>
}
<br>