;This closure extracts a frame from the input buffer, and calls the TSM kernel
;This frame is then copied to the output buffer.
;Provided are 2 separate stereo versions of TSM processing. The Mid side versions
;give the most accurate stereo image. The standard LR version requires the least
;processing overhead, but quickly loses phase coherance between the channels.
(bind-func store_frame_sPL
(lambda (window_size:i64)
(let ((read_head:i64 0)
(write_head:i64 0)
;(PV_left (phase_vocoder_sPL (/ window_size IN_CHANNELS)))
;(PV_right (phase_vocoder_sPL (/ window_size IN_CHANNELS)))
(PV_mid (phase_vocoder_sPL (/ window_size 2))) ;replace 2 with IN_CHANNELS if using 0.7.0 release
(PV_side (phase_vocoder_sPL (/ window_size 2)))) ;replace 2 with IN_CHANNELS if using 0.7.0 release
(lambda (input_buffer:float* in_size:i64 output_buffer:float* out_size:i64 Sa:i64 Ss:i64)
(let ((n:i64 0)
(window_buffer_in:float* (salloc window_size))
(window_buffer_out:float* (salloc window_size))
(left_right_size:i64 (/ window_size 2)) ;replace 2 with IN_CHANNELS if using 0.7.0 release
;(left:float* (salloc left_right_size))
;(right:float* (salloc left_right_size))
(mid:float* (salloc left_right_size))
(side:float* (salloc left_right_size)))
(dotimes (n window_size)
(pset! window_buffer_in n (pref input_buffer (% (+ n read_head) in_size))))
(set! read_head (% (+ read_head Sa ) in_size)) ;Advance the playhead by the Analysis hopsize
;;Standard Left Right processing
;(make_mono window_buffer_in window_size)
;(LR_split window_buffer_in left right window_size)
;(PV_left left (/ Sa IN_CHANNELS) (/ Ss IN_CHANNELS))
;(PV_right right (/ Sa IN_CHANNELS) (/ Ss IN_CHANNELS))
;(LR_combine window_buffer_out left right window_size)
;(make_mono window_buffer_out window_size)
;;Two channel MS Processing (best stereo image)
(LR_to_MS_2_channels window_buffer_in window_size mid side)
(PV_mid mid (/ Sa 2) (/ Ss 2)) ;replace 2 with IN_CHANNELS if using 0.7.0 release
(PV_side side (/ Sa 2) (/ Ss 2)) ;replace 2 with IN_CHANNELS if using 0.7.0 release
(MS_to_LR_2_channels window_buffer_out window_size mid side)
(dotimes (n window_size) ;Overlap-Add section
(cond ((< n (- window_size Ss))
(pset! output_buffer (% (+ write_head n) out_size) (+ (pref window_buffer_out n)
(pref output_buffer (% (+ write_head n) out_size)))))
(else
(pset! output_buffer (% (+ write_head n) out_size) (pref window_buffer_out n)))))
(set! write_head (% (+ write_head Ss ) out_size))
(set! TSM_active 1)
void
)))))