;; an accumulative adsr (random access not allowed! time must be linear).
(bind-func static adsr_accum_c
(lambda (start_time:i64 atk_dur:i64 dky_dur:i64 sus_dur:i64 rel_dur:i64 peak_amp:SAMPLE sus_amp:SAMPLE)
(if (or (= atk_dur 0) (= dky_dur 0))
(begin (set! dky_dur 0)
(set! peak_amp sus_amp)))
(let ((val:SAMPLE (if (> (+ atk_dur dky_dur) 1) 0.0 peak_amp))
(t1 (+ atk_dur start_time))
(t2 (+ atk_dur dky_dur start_time))
(t3 (+ atk_dur dky_dur sus_dur start_time))
(t4 (+ atk_dur dky_dur sus_dur rel_dur start_time))
(inc1:SAMPLE (/ peak_amp (convert atk_dur)))
(inc2 (* -1.0 (/ (- peak_amp sus_amp) (convert dky_dur))))
(inc3 (* -1.0 (/ sus_amp (convert rel_dur)))))
(lambda (time:i64 chan:i64)
(if (= chan 0)
(cond ((> time t4) (set! val 0.0))
((> time t3) (set! val (+ val inc3)))
((> time t2) val) ;; sustain (don't do anything with val)
((> time t1) (set! val (+ val inc2)))
((> time start_time) (set! val (+ val inc1)))
(else (set! val 0.0))))
val))))