;; iir comb with interpolation
;; delay for COMB needs to stay
;; as a fractional argument (i.e. float)
(bind-func static comb_c
(lambda (maxdelay:i64)
(let ((line:SAMPLE* (zalloc maxdelay))
(in_head 0)
(out_head 0)
(out_head_alpha 0)
(olddelay:SAMPLE (convert maxdelay))
(alpha 0.0)
(i:i64 0)
(idelay:i64 0)
(delayed:SAMPLE 0.0)
(delayedY:SAMPLE 0.0)
(delayedY1:SAMPLE 0.0)
(delayedLin:SAMPLE 0.0)) ;; linear interp
(dotimes (i maxdelay) (pset! line i 0.0))
(lambda (x:SAMPLE delay:SAMPLE in:SAMPLE mix:SAMPLE fb:SAMPLE)
(if (<> delay olddelay)
(begin (set! olddelay delay)
(set! alpha (- delay (floor delay)))
(set! idelay (convert (floor delay)))
(set! out_head (- (+ maxdelay in_head) idelay))
(set! out_head_alpha (- (+ maxdelay in_head) (+ 1 idelay)))))
(if (> out_head maxdelay) (set! out_head (- out_head maxdelay)))
(if (> out_head_alpha maxdelay) (set! out_head_alpha (- out_head_alpha maxdelay)))
(if (> in_head maxdelay) (set! in_head (- in_head maxdelay)))
(set! delayedY1 (pref line out_head))
(set! delayedY (pref line out_head_alpha))
(set! delayedLin (* (- delayedY delayedY1) alpha))
(set! delayed (+ delayedY1 delayedLin))
(pset! line in_head (+ (* in x) (* fb delayed)))
(set! in_head (+ in_head 1))
(set! out_head (+ out_head 1))
(set! out_head_alpha (+ out_head_alpha 1))
(+ (* x (- 1.0 mix)) (* delayed mix))))))