You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
1.8 KiB
85 lines
1.8 KiB
#ifndef __ADSR_H__
|
|
#define __ADSR_H__
|
|
|
|
#include <cmath>
|
|
|
|
#include "../util.h"
|
|
|
|
class ADSR {
|
|
public:
|
|
typedef struct {
|
|
float attackStep;
|
|
float decayStep;
|
|
float sustain;
|
|
float releaseStep;
|
|
} Envelope;
|
|
|
|
Envelope const * env;
|
|
|
|
ADSR() : state(IDLE), t(0), last(0) {};
|
|
void reset();
|
|
void assign(Envelope const * env);
|
|
void noteOn();
|
|
void noteOff();
|
|
bool isIdle() {
|
|
return state == IDLE;
|
|
}
|
|
|
|
inline float tick() {
|
|
switch(state) {
|
|
case IDLE:
|
|
return 0;
|
|
|
|
case ATTACK:
|
|
if(t < 1) {
|
|
t += env->attackStep;
|
|
last = t*t;
|
|
} else {
|
|
state = DECAY;
|
|
t = 1;
|
|
last = 1;
|
|
}
|
|
break;
|
|
|
|
case DECAY:
|
|
if(t > 0) {
|
|
t -= env->decayStep;
|
|
//last = env->sustain + (1 - env->sustain) * curve(t);
|
|
last = env->sustain + (1 - env->sustain) * t*t;
|
|
} else {
|
|
state = SUSTAIN;
|
|
t = 1;
|
|
last = env->sustain;
|
|
}
|
|
break;
|
|
|
|
case SUSTAIN:
|
|
last = env->sustain;
|
|
break;
|
|
|
|
case RELEASE:
|
|
if(t > 0) {
|
|
t -= env->releaseStep;
|
|
return last * t*t;
|
|
} else {
|
|
state = IDLE;
|
|
t = 0;
|
|
last = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return last;
|
|
}
|
|
|
|
private:
|
|
enum { IDLE, ATTACK, DECAY, SUSTAIN, RELEASE } state;
|
|
float t;
|
|
float last;
|
|
|
|
float curve(float gain) {
|
|
return 0.5f - 0.5f * cosf(clamp(gain * (float) M_PI, 0.f, M_PI));
|
|
}
|
|
};
|
|
|
|
#endif |