;; linear sampler
;;
;; faster but noisy
(bind-func sampler_note_linear
(lambda ()
(let ((amp_env:|4,float| (array 10.0:f 50.0 0.6 200.0)))
(lambda (data:NoteData* samples:|128,SAMPLE*|* samples_length:|128,i64|* samples_offsets:|128,i64|* samples_channels:|128,i64|* index:i64 nargs:i64 dargs)
(let ((starttime (note_starttime data))
(freq (note_frequency data))
(amp (note_amplitude data))
(duration (note_duration data))
(gate 1.0:f)
(pan:SAMPLE (if (> nargs 1) (pref dargs 1) 0.5)) ;; first darg is bank
(offset:SAMPLE (if (> nargs 2) (pref dargs 2) 0.0))
(rev:i1 (if (> nargs 3) (if (> (pref dargs 3) 0.01) #t #f) #f))
(a (aref amp_env 0))
(d (aref amp_env 1))
(s (aref amp_env 2))
(r (aref amp_env 3))
(rtime:i64 (convert (* SRf (/ (aref amp_env 3) 1000.0))))
(dt 0) (rt 0)
(total_time (+ duration rtime))
(env (adsr_c))
(eamp 0.0)
(idx_freq (convert (midi2frq (convert index))))
(phase:double (convert (+ offset (convert (aref samples_offsets index)))))) ;; phase unit is audio frames
(if (and rev (< phase 0.01))
(set! phase (convert (- (aref samples_length index) 10))))
(lambda (time:i64 chan:i64)
(if (= chan 0)
(begin
(set! dt (+ dt 1))
(if (> dt duration) (set! gate 0.0))
(set! eamp (env chan gate a d s r))
(if (< gate 0.1)
(begin (set! rt (+ rt 1))
(if (> rt rtime) (note_active data #f))))))
(let ((rate:double (/ (convert freq) idx_freq))
(pos:double (if (= chan 0) ;; only increment once per frame
(if rev
(set! phase (- phase rate))
(set! phase (+ phase rate)))
phase))
(posi:i64 (convert (floor pos)))
(posx (+ (* posi 2) chan))
(lgth:i64 (convert (- (aref samples_length index) 10)))
(dat (aref samples index)))
(* amp eamp (if (or (> posi lgth) (< posi 0)) 0.0 (pref dat posx))))))))))