;; adsr with initial delay in ms
(bind-func static dadsr_c
(lambda ()
(let ((calcCoef (lambda (rate:float targetRatio:float)
(exp (/ (* -1.0 (log (/ (+ 1.0 targetRatio)
targetRatio)))
rate))))
(retrigger:i1 0)
(targetRatioA 0.3)
(targetRatioDR 0.0001)
(env_idle 0) (env_attack 1) (env_decay 2) (env_sustain 3) (env_release 4) (env_predelay 5)
(state env_idle)
(attackRate 0.0)
(attackCoef 0.0)
(attackBase 0.0)
(decayRate 0.0)
(decayCoef 0.0)
(decayBase 0.0)
(sustainLevel 0.0)
(releaseRate 0.0)
(releaseCoef 0.0)
(releaseBase 0.0)
(delay 0:i64)
(old_g 0.0)
(old_a -1.0)
(old_d -1.0)
(old_s -1.0)
(old_r -1.0)
(out 0.0))
(lambda (chan:i64 g:SAMPLE del a d s r)
(if (= chan 0)
(begin
(if retrigger
(begin (set! retrigger 0)
;; (set! out 0.0)
(set! state env_attack)))
(if (<> a old_a)
(begin
(set! old_a a)
(set! attackRate (* a SRf 0.001))
(set! attackCoef (calcCoef attackRate targetRatioA))
(set! attackBase (* (+ 1.0 targetRatioA) (- 1.0 attackCoef)))))
(if (<> d old_d)
(begin
(set! old_d d)
(set! decayRate (* d SRf 0.001))
(set! decayCoef (calcCoef decayRate targetRatioDR))
(set! decayBase (* (- sustainLevel targetRatioDR) (- 1.0 decayCoef)))))
(if (<> s old_s)
(begin
(set! old_s s)
(set! sustainLevel s)
(set! decayBase (* (- sustainLevel targetRatioDR) (- 1.0 decayCoef)))))
(if (<> r old_r)
(begin
(set! old_r r)
(set! releaseRate (* r SRf 0.001))
(set! releaseCoef (calcCoef releaseRate targetRatioDR))
(set! releaseBase (* -1.0 targetRatioDR (- 1.0 releaseCoef)))))
(if (<> g old_g)
(if (> g 0.1)
(cond ((> del 0.00001)
(set! state env_predelay)
(set! delay (ftoi64 (* del SRf 0.001))))
((> a 0.00001) (set! state env_attack))
((> d 0.00001) (set! out 1.0) (set! state env_decay))
(else (set! out sustainLevel) (set! state env_sustain)))
(set! state env_release)))
(set! old_g g)
(cond ((= state env_idle)
out)
((= state env_predelay)
(set! delay (- delay 1))
(if (<= delay 0)
(cond ((> a 0.00001) (set! state env_attack))
((> d 0.00001) (set! out 1.0) (set! state env_decay))
(else (set! out sustainLevel) (set! state env_sustain))))
out)
((= state env_attack)
(set! out (+ attackBase (* out attackCoef)))
(if (>= out 1.0)
(begin (set! out 1.0)
(set! state env_decay)))
out)
((= state env_decay)
(set! out (+ decayBase (* out decayCoef)))
(if (<= out sustainLevel)
(begin (set! out sustainLevel)
(set! state env_sustain)))
out)
((= state env_sustain) out)
((= state env_release)
(set! out (+ releaseBase (* out releaseCoef)))
(if (<= out 0.0)
(begin (set! out 0.0)
(set! state env_idle)))
out)))
out)))))