;; where pw is between 0.0 - 1.0
;; and chooses between 'segments' of the audio file
;; where a segment is 1 * looplgth samples long
;; the number of segments is then frames / looplgth
(bind-func AudioBuffer_read_interp_pw
(lambda (buffer:AudioBuffer* freq:SAMPLE chan:i64 pw:float)
(set! pw (* pw 0.9999999))
(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))
(offset (* (convert (floor (* pw (convert segments)))) looplgth))
(mix (% (* pw (convert segments)) 1.0))
(dat1 (AudioBuffer_ptr buffer offset chan))
(dat2 (AudioBuffer_ptr buffer (% (+ offset looplgth) frames) chan))
(dy1 0.0) (dx0 0.0) (dx1 0.0) (dx2 0.0)
(y1 0.0) (x0 0.0) (x1 0.0) (x2 0.0)
(y1pos:i64 (* channels (convert (floor (% (- pos rate) lgthf)))))
(x0pos:i64 (* channels (convert (floor pos))))
(x1pos:i64 (* channels (convert (floor (% (+ pos rate) lgthf)))))
(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! dy1 (- (pref dat2 y1pos) (pref dat1 y1pos)))
(set! y1 (if (and oneshot (< x0pos 1)) 0.0 (+ (pref dat1 y1pos) (* dy1 mix))))
(set! dx0 (- (pref dat2 x0pos) (pref dat1 x0pos)))
(set! x0 (+ (pref dat1 x0pos) (* dx0 mix)))
(set! dx1 (- (pref dat2 x1pos) (pref dat1 x1pos)))
(set! x1 (+ (pref dat1 x1pos) (* dx1 mix)))
(set! dx2 (- (pref dat2 x2pos) (pref dat1 x2pos)))
(set! x2 (+ (pref dat1 x2pos) (* dx2 mix)))
(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))))))