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.
74 lines
1.5 KiB
74 lines
1.5 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;
|
|
|
|
const Envelope* env;
|
|
|
|
ADSR() = delete;
|
|
ADSR(const Envelope *env);
|
|
void noteOn();
|
|
void noteOff();
|
|
|
|
inline float tick() {
|
|
float out = curve(gain);
|
|
|
|
switch(state) {
|
|
case IDLE:
|
|
break;
|
|
|
|
case ATTACK:
|
|
if(gain < 1) {
|
|
gain += env->attackStep;
|
|
} else {
|
|
state = DECAY;
|
|
gain = 1;
|
|
}
|
|
break;
|
|
|
|
case DECAY:
|
|
if(gain > env->sustain) {
|
|
gain -= env->decayStep;
|
|
} else {
|
|
state = SUSTAIN;
|
|
gain = env->sustain;
|
|
}
|
|
break;
|
|
|
|
case SUSTAIN:
|
|
break;
|
|
|
|
case RELEASE:
|
|
if(gain > 0) {
|
|
gain -= env->releaseStep;
|
|
} else {
|
|
state = IDLE;
|
|
gain = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
private:
|
|
enum { IDLE, ATTACK, DECAY, SUSTAIN, RELEASE } state;
|
|
float gain;
|
|
|
|
float curve(float gain) {
|
|
return 0.5 - 0.5 * cos(clamp(gain * M_PI, 0, M_PI));
|
|
}
|
|
};
|
|
|
|
#endif |