;; no pulsewidth, faster but no segments or mixing
(bind-func AudioBuffer_read_interp
(lambda (buffer:AudioBuffer* freq:SAMPLE chan:i64)
(let ((channels:i64 (AudioBuffer_channels buffer))
(frames (AudioBuffer_frames buffer))
(looplgth (AudioBuffer_loop_frames buffer))
(loopstart (AudioBuffer_loop_start buffer))
(oneshot (= looplgth 0))
(segments (if oneshot 0 (/ frames looplgth)))
(phase:double (AudioBuffer_phase buffer))
(rate (/ (convert freq) (convert (midi2frq_local (convert (AudioBuffer_root_pitch buffer))))))
(pos:double phase)
(lgth:i64 (if oneshot
(- (- frames 1) loopstart)
(clamp looplgth
0
(- frames loopstart))))
(lgthf:double (convert lgth))
(dat (AudioBuffer_ptr buffer (clamp loopstart 0 (- frames looplgth)) chan))
(y1 0.0)
(y1pos:i64 (* channels (convert (floor (% (- pos rate) lgthf)))))
(x0 0.0)
(x0pos:i64 (* channels (convert (floor pos))))
(x1 0.0)
(x1pos:i64 (* channels (convert (floor (% (+ pos rate) lgthf)))))
(x2 0.0)
(x2pos:i64 (* channels (convert (floor (% (+ pos rate rate) lgthf))))))
(if (> pos lgthf) 0.0 ;; return silence when past the end (shouldn't happen if looping)
(begin
(set! y1 (if (and oneshot (< x0pos 1)) 0.0 (pref dat y1pos)))
(set! x0 (pref dat x0pos))
(set! x1 (pref dat x1pos))
(set! x2 (pref dat x2pos))
(if (= chan 0) ;; increment phase
(AudioBuffer_set_phase buffer
(if oneshot
(+ pos rate)
(% (+ pos rate) lgthf))))
;; return interpolated result
(hermite_interp_local (dtof (% pos 1.0)) y1 x0 x1 x2))))))