diff options
author | Florian Jung <flo@thinkpad.(none)> | 2010-12-29 16:55:25 +0100 |
---|---|---|
committer | Florian Jung <flo@thinkpad.(none)> | 2010-12-29 16:55:25 +0100 |
commit | 7113f02ae87482211aec5046f9ac46c3cc9ad017 (patch) | |
tree | b6484b45317e7e80567d9902cf94843d227ce30e /synth/envelope.cpp |
Initial commit
Diffstat (limited to 'synth/envelope.cpp')
-rw-r--r-- | synth/envelope.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/synth/envelope.cpp b/synth/envelope.cpp new file mode 100644 index 0000000..481b78f --- /dev/null +++ b/synth/envelope.cpp @@ -0,0 +1,168 @@ +#include "envelope.h" + +Envelope::Envelope(jack_nframes_t a, jack_nframes_t d, fixed_t s, jack_nframes_t r, bool h) +{ + level=0; + t=0; + state=ATTACK; + max=ONE; + + set_ratefactor(1.0); + + set_attack(a); + set_decay(d); + set_sustain(s); + set_release(r); + set_hold(h); +} + +Envelope::Envelope(env_settings_t s) +{ + level=0; + t=0; + state=ATTACK; + max=ONE; + + set_ratefactor(1.0); + + set_attack(s.attack); + set_decay(s.decay); + set_sustain(s.sustain); + set_release(s.release); + set_hold(s.hold); +} + +void Envelope::set_ratefactor(double factor) +{ + ratefactor=ONE*factor; + + set_attack(attack_orig); + set_decay(decay_orig); + set_release(release_orig); +} + +void Envelope::set_attack(jack_nframes_t a) +{ + attack_orig=a; + attack=a*ratefactor >>SCALE; + + if (state==ATTACK) + t=attack*level >>SCALE; +} + +void Envelope::set_decay(jack_nframes_t d) +{ + decay_orig=d; + decay=d*ratefactor >>SCALE; + + if ((state==DECAY) && (sustain!=ONE)) + if (sustain<ONE) //to avoid a div. by zero + t=decay*(ONE-level)/(ONE-sustain); +} + +void Envelope::set_sustain(fixed_t s) +{ + sustain=s; + sustain_orig=s; +} + +void Envelope::set_release(jack_nframes_t r) +{ + release_orig=r; + release=r*ratefactor >>SCALE; + + if (state==RELEASE) + if (sustain>0) //to avoid a div. by zero + t=release*(sustain-level)/sustain; +} + + +void Envelope::set_hold(bool h) +{ + hold=h; + if ((h==false) && (state==HOLD)) + { + t=0; + state=RELEASE; + } +} + +void Envelope::reattack() +{ + state=ATTACK; + t=attack*level >>SCALE; + sustain=sustain_orig; +} + +void Envelope::release_key() +{ + if ((state!=RELEASE) && (state!=DONE)) + { + t=0; + state=RELEASE; + sustain=level; + } +} + +bool Envelope::still_active() +{ + return (state!=DONE); +} + +fixed_t Envelope::get_level() //must be called each frame +{ + switch (state) + { + case ATTACK: + if (t>=attack) + { + level=max; + state=DECAY; + t=0; + } + else //will only happen, if t < attack. so attack will + { //always be greater than zero -> no div. by zero + level=max * t / attack ; + } + break; + + case DECAY: + if (t>=decay) + { + level=max*sustain >>SCALE; + if (hold) + state=HOLD; + else + state=RELEASE; + t=0; + } + else //will only happen, if t < decay. so decay will + { //always be greater than zero -> no div. by zero + level=(ONE - (ONE-sustain)*t/decay)*max >>SCALE; + } + break; + + case HOLD: + level=sustain*max >>SCALE; + break; + + case RELEASE: + if (t>=release) + { + level=0; + state=DONE; + } + else //will only happen, if t < release. so release will + { //always be greater than zero -> no div. by zero + level=(sustain - sustain * t/release)*max >>SCALE; + } + break; + + case DONE: + level=0; + break; + } + + t++; + return level; +} |