(bind-func analogueVec_note
(lambda ()
(let ((MILLISEC (* .001 SRs))
(amp_env:|4,SAMPLE| (array 0.0:f 0.0 1.0 0.0))
(filter_env:|4,SAMPLE| (array 0.0:f 0.0 1.0 0.0))
(pitch_env:|2,SAMPLE| (array 0.0:f 0.0))
(mod_env:|4,SAMPLE| (array 0.0:f 0.0 1.0 0.0))
(oldfreq 440.0:f)
(tune1:SAMPLE 1.0)
(tune2:SAMPLE 1.0)
(tune3:SAMPLE 1.0)
(tune4:SAMPLE 1.0)
(osc1_wave:enum PARAM_SAW)
(osc2_wave:enum PARAM_SAW)
(osc3_wave:enum PARAM_SAW)
(osc4_wave:enum PARAM_SAW)
(pw1:SAMPLE 0.5)
(pw2:SAMPLE 0.5)
(pw3:SAMPLE 0.5)
(pw4:SAMPLE 0.5)
(noise:enum PARAM_WHITE) ;; white
(noise_amp:SAMPLE 0.0)
(osc1_amp:SAMPLE 0.4)
(osc2_amp:SAMPLE 0.0)
(osc3_amp:SAMPLE 0.0)
(osc4_amp:SAMPLE 0.0)
(osc_slop:SAMPLE 0.0)
(sub_amp:SAMPLE 0.0)
(mods:|32,SAMPLE|* (alloc))
(noise_amp_mod:SAMPLE 0.0)
(filter_type:i64 2) ;; LPF2 LPF4, HPF2 HPF4, BPF2 BPF4
(follow_frq 0.0)
(follow_amp 0.0)
(legato #f) ;; if legato is true then don't retrigger adsr's!
(filter_frq:SAMPLE 15000.0) ;;
(filter_env_amt:SAMPLE 0.0) ;; this for lpf
(filter_saturation:SAMPLE 1.0)
(pitch_env_amt:SAMPLE 0.0)
(portamento:SAMPLE 2.0) ;; in millis
(res:SAMPLE 0.0)
(reso:SAMPLE 0.0))
(lambda (data:NoteData* nargs:i64 dargs:SAMPLE*)
(let ((starttime:i64 (note_starttime data))
(frequency:SAMPLE (+ (note_frequency data) (* (- (random) 0.5) (note_frequency data) osc_slop 0.05)))
(target_frq:SAMPLE frequency)
(amplitude:SAMPLE (note_amplitude data))
(target_amp:SAMPLE amplitude)
(newampinc:SAMPLE 0.0)
(duration:i64 (note_duration data))
(glideinc:SAMPLE 0.0) ;; for portamento
(midifrq:SAMPLE 0.0)
(new_note_timer:i64 0)
(frq 0.0)
(osc_pws_v (vector pw1 pw2 pw3 pw4))
(osc_tunes_v (vector tune1 tune2 tune3 tune4))
(osc_modamps_v (vector (aref mods PARAM_OSC1_AMP) (aref mods PARAM_OSC2_AMP) (aref mods PARAM_OSC3_AMP) (aref mods PARAM_OSC4_AMP)))
(osc_modfrqs_v (vector (aref mods PARAM_OSC1_FRQ) (aref mods PARAM_OSC2_FRQ) (aref mods PARAM_OSC3_FRQ) (aref mods PARAM_OSC4_FRQ)))
(osc_modpws_v (vector (aref mods PARAM_OSC1_PW) (aref mods PARAM_OSC2_PW) (aref mods PARAM_OSC3_PW) (aref mods PARAM_OSC4_PW)))
(osc_amps_v (vector osc1_amp osc2_amp osc3_amp osc4_amp))
(osc_amp_v (vector 1.0:f 1.0 1.0 1.0))
(osc_frq_v (vector 1.0:f 1.0 1.0 1.0))
(osc_tune_v (vector 1.0:f 1.0 1.0 1.0))
(osc_pw_v (vector 1.0:f 1.0 1.0 1.0))
(osc_tmp_v (vector 1.0:f 1.0 1.0 1.0))
(osc_out_v (vector 1.0:f 1.0 1.0 1.0))
(adsr4_v (vector 1.0:f 1.0 1.0 1.0))
(adsr1 (adsr_c))
(adsr2 (adsr_c))
(adsr3 (adsr_c))
(adsr4 (adsr_c))
(adsr1_val 0.0)
(adsr2_val 0.0)
(adsr3_val 0.0)
(adsr4_val 0.0)
;; (gate:SAMPLE 1.0)
(amp:SAMPLE 0.0)
(cof:SAMPLE 0.0)
(amp_attack (aref amp_env 0))
(amp_decay (aref amp_env 1))
(amp_sustain (aref amp_env 2))
(amp_release (+ 3.0 (aref amp_env 3))) ;; a 3ms release minimum
(amp_release_samples (convert (* SRs (/ amp_release 1000.0)) i64))
(reltime:i64 0)
(filter_attack (aref filter_env 0))
(filter_decay (aref filter_env 1))
(filter_sustain (aref filter_env 2))
(filter_release (aref filter_env 3))
(pitch_attack (aref pitch_env 0))
(pitch_decay (aref pitch_env 1))
(mod_attack (aref mod_env 0))
(mod_decay (aref mod_env 1))
(mod_sustain (aref mod_env 2))
(mod_release (aref mod_env 3))
(filter:[SAMPLE,SAMPLE,SAMPLE,SAMPLE]* (moog_ladder_inlined (i64toi32 filter_type)))
(osc1 (cond ((= osc1_wave 1) (blsawXAnalogue_c (* .025 (random)) #f #f))
((= osc1_wave 2) (blpulse_c 1.0 #f))
((= osc1_wave 3) (bltriXAnalogue_c 1.0))
((= osc1_wave 0) (oscXAnalogue_c (* .025 (random))))
(else (oscXAnalogue_c (* .025 (random)))))) ;; else sin
(osc2 (cond ((= osc1_wave 1) (blsawXAnalogue_c (* .025 (random)) #f #f))
((= osc1_wave 2) (blpulse_c 1.0 #f))
((= osc1_wave 3) (bltriXAnalogue_c 1.0))
((= osc1_wave 0) (oscXAnalogue_c (* .025 (random))))
(else (oscXAnalogue_c (* .025 (random)))))) ;; else sin
(osc3 (cond ((= osc1_wave 1) (blsawXAnalogue_c (* .025 (random)) #f #f))
((= osc1_wave 2) (blpulse_c 1.0 #f))
((= osc1_wave 3) (bltriXAnalogue_c 1.0))
((= osc1_wave 0) (oscXAnalogue_c (* .025 (random))))
(else (oscXAnalogue_c (* .025 (random)))))) ;; else sin
(osc4 (cond ((= osc1_wave 1) (blsawXAnalogue_c (* .025 (random)) #f #f))
((= osc1_wave 2) (blpulse_c 1.0 #f))
((= osc1_wave 3) (bltriXAnalogue_c 1.0))
((= osc1_wave 0) (oscXAnalogue_c (* .025 (random))))
(else (oscXAnalogue_c (* .025 (random)))))) ;; else sin which is cheapest
(osc1_out:SAMPLE 0.0)
(osc2_out:SAMPLE 0.0)
(osc3_out:SAMPLE 0.0)
(osc4_out:SAMPLE 0.0)
(zero:SAMPLE 0.0)
(white (white_c))
(pink (pink_c))
(sub_out 0.0)
(noise_out 0.0)
(subosc (osc_c 0.0))
(main_out 0.0:f))
(filter.saturation (clamp filter_saturation 1.0:f 3.0:f))
(lambda (time:i64 chan:i64)
(if (= chan 0)
(begin
;; this for voice steeling
(if (<> starttime (tref data 1))
(begin
(println "steeling voice:" (convert (frq2midi frequency) i64))
(set! starttime (note_starttime data))
(set! frequency (note_frequency data))
(set! duration (note_duration data))))
(if (and (> (note_gate data) 0.5) (> (- time starttime) duration)) (note_gate data 0.0)) ;; (set! gate 0.0))
(set! adsr1_val (adsr1 chan (note_gate data) amp_attack amp_decay amp_sustain amp_release))
(set! adsr2_val (adsr2 chan (note_gate data) filter_attack filter_decay filter_sustain filter_release))
(set! adsr3_val (adsr3 chan (note_gate data) pitch_attack pitch_decay 0.0 0.0))
(set! adsr4_val (adsr4 chan (note_gate data) mod_attack mod_decay mod_sustain mod_release))
(set! amp (* amplitude adsr1_val))
(set! cof (clamp (+ filter_frq (* follow_frq 8.0 frequency) (* follow_amp amplitude 12000.0)
(* adsr4_val (aref mods PARAM_FILTER_FRQ))
(* filter_env_amt adsr2_val))
0.0 22000.0))
(set! res (+ reso (* adsr4_val (aref mods PARAM_FILTER_RES))))
(set! frq (+ frequency (* pitch_env_amt frequency adsr3_val) 0.0))
(if (< frq 10.0) (set! frq 10.0))
;; if gate is OFF and amp is sufficiently close to 0.0 then stop note!
(if (< (note_gate data) 0.1) (set! reltime (+ reltime 1)))
(if (> reltime amp_release_samples)
(begin
;; (println "NOTE OFF!" data)
(note_active data #f)))
;; 4 * oscillators
(set! adsr4_v (vector adsr4_val adsr4_val adsr4_val adsr4_val))
(set! osc_amp_v (+ osc_amps_v (* adsr4_v osc_modamps_v)))
(set! osc_frq_v (+ (* (vector frq frq frq frq) osc_tunes_v) (* adsr4_v osc_modfrqs_v)))
(set! osc_pw_v (+ osc_pws_v (* adsr4_v osc_modpws_v)))
(set! osc_out_v (* osc_amp_v (vector (if (> osc1_amp 0.001) (osc1 1.0 (vref osc_frq_v 0) (vref osc_pw_v 0)) 0.0)
(if (> osc2_amp 0.001) (osc2 1.0 (vref osc_frq_v 1) (vref osc_pw_v 1)) 0.0)
(if (> osc3_amp 0.001) (osc3 1.0 (vref osc_frq_v 2) (vref osc_pw_v 2)) 0.0)
(if (> osc1_amp 0.001) (osc4 1.0 (vref osc_frq_v 3) (vref osc_pw_v 3)) 0.0))))
(if (> sub_amp 0.001)
(set! sub_out (* sub_amp (subosc 1.0 (* frq 0.25))))
(set! sub_out 0.0))
(if (> noise_amp 0.001)
(if (= noise PARAM_WHITE)
(set! noise_out (* 0.5 (+ noise_amp (* adsr4_val (aref mods PARAM_NOISE_AMP))) (white)))
(set! noise_out (* 0.5 (+ noise_amp (* adsr4_val (aref mods PARAM_NOISE_AMP))) (pink))))
(set! noise_out 0.0))
(set! main_out (* amp (filter
(+ (vref osc_out_v 0)
(vref osc_out_v 1)
(vref osc_out_v 2)
(vref osc_out_v 3)
sub_out
noise_out)
cof reso)))))
main_out))))))