Files
stk/ADSR.cpp
Gary Scavone ea749b71d2 Version 2.01
2013-09-29 22:39:45 +02:00

198 lines
4.1 KiB
C++

/*******************************************/
/* ADSR Subclass of the Envelope Class, */
/* by Perry R. Cook, 1995-96 */
/* This is the traditional ADSR (Attack */
/* Decay, Sustain, Release) ADSR. */
/* It responds to simple KeyOn and KeyOff */
/* messages, keeping track of it's state. */
/* There are two tick (update value) */
/* methods, one returns the value, and */
/* other returns the state (0 = A, 1 = D, */
/* 2 = S, 3 = R) */
/*******************************************/
#include "ADSR.h"
ADSR :: ADSR() : Envelope()
{
target = (MY_FLOAT) 0.0;
value = (MY_FLOAT) 0.0;
attackRate = (MY_FLOAT) 0.001;
decayRate = (MY_FLOAT) 0.001;
sustainLevel = (MY_FLOAT) 0.5;
releaseRate = (MY_FLOAT) 0.01;
state = 0;
}
ADSR :: ~ADSR()
{
/* Nothing to do here */
}
void ADSR :: keyOn()
{
target = (MY_FLOAT) 1.0;
rate = attackRate;
state = 0;
}
void ADSR :: keyOff()
{
target = (MY_FLOAT) 0.0;
rate = releaseRate;
state = 3;
}
void ADSR :: setAttackRate(MY_FLOAT aRate)
{
if (aRate < 0.0) {
printf("negative rates not allowed!!, correcting\n");
attackRate = -aRate;
}
else attackRate = aRate;
}
void ADSR :: setDecayRate(MY_FLOAT aRate)
{
if (aRate < 0.0) {
printf("negative rates not allowed!!, correcting\n");
decayRate = -aRate;
}
else decayRate = aRate;
}
void ADSR :: setSustainLevel(MY_FLOAT aLevel)
{
if (aLevel < 0.0 ) {
printf("Sustain level out of range!!, correcting\n");
sustainLevel = (MY_FLOAT) 0.0;
}
else sustainLevel = aLevel;
}
void ADSR :: setReleaseRate(MY_FLOAT aRate)
{
if (aRate < 0.0) {
printf("negative rates not allowed!!, correcting\n");
releaseRate = -aRate;
}
else releaseRate = aRate;
}
void ADSR :: setAttackTime(MY_FLOAT aTime)
{
if (aTime < 0.0) {
printf("negative times not allowed!!, correcting\n");
attackRate = ONE_OVER_SRATE / -aTime;
}
else attackRate = ONE_OVER_SRATE / aTime;
}
void ADSR :: setDecayTime(MY_FLOAT aTime)
{
if (aTime < 0.0) {
printf("negative times not allowed!!, correcting\n");
decayRate = ONE_OVER_SRATE / -aTime;
}
else decayRate = ONE_OVER_SRATE / aTime;
}
void ADSR :: setReleaseTime(MY_FLOAT aTime)
{
if (aTime < 0.0) {
printf("negative times not allowed!!, correcting\n");
releaseRate = ONE_OVER_SRATE / -aTime;
}
else releaseRate = ONE_OVER_SRATE / aTime;
}
void ADSR :: setAllTimes(MY_FLOAT attTime, MY_FLOAT decTime, MY_FLOAT susLevel, MY_FLOAT relTime)
{
this->setAttackTime(attTime);
this->setDecayTime(decTime);
this->setSustainLevel(susLevel);
this->setReleaseTime(relTime);
}
void ADSR :: setTarget(MY_FLOAT aTarget)
{
target = aTarget;
if (value < target) {
state = ATTACK;
this->setSustainLevel(target);
rate = attackRate;
}
if (value > target) {
this->setSustainLevel(target);
state = DECAY;
rate = decayRate;
}
}
void ADSR :: setValue(MY_FLOAT aValue)
{
state = SUSTAIN;
target = aValue;
value = aValue;
this->setSustainLevel(aValue);
rate = (MY_FLOAT) 0.0;
}
MY_FLOAT ADSR :: tick()
{
if (state==ATTACK) {
value += rate;
if (value >= target) {
value = target;
rate = decayRate;
target = sustainLevel;
state = DECAY;
}
}
else if (state==DECAY) {
value -= decayRate;
if (value <= sustainLevel) {
value = sustainLevel;
rate = (MY_FLOAT) 0.0;
state = SUSTAIN;
}
}
else if (state==RELEASE) {
value -= releaseRate;
if (value <= 0.0) {
value = (MY_FLOAT) 0.0;
state = 4;
}
}
return value;
}
int ADSR :: informTick()
{
this->tick();
return state;
}
MY_FLOAT ADSR :: lastOut()
{
return value;
}
/************ Test Main ************************/
/*
void main()
{
long i;
ADSR test;
test.setAttackRate(0.15);
test.keyOn();
while(test.informTick()==ATTACK) printf("%lf\n",test.tick());
test.setDecayRate(0.1);
while (test.informTick()==DECAY) printf("%lf\n",test.lastOut());
test.setReleaseRate(0.05);
test.keyOff();
while(test.informTick()==RELEASE) printf("%lf\n",test.lastOut());
}
*/