;; performance profile (0 high, 1 low)
(bind-func analogue_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))
(mod_env_delay:SAMPLE 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.25)
(osc2_amp:SAMPLE 0.0)
(osc3_amp:SAMPLE 0.0)
(osc4_amp:SAMPLE 0.0)
(osc_phase_slop 0.1)
(osc1_phase:SAMPLE (* osc_phase_slop .1 (random)))
(osc2_phase:SAMPLE (* osc_phase_slop .1 (random)))
(osc3_phase:SAMPLE (* osc_phase_slop .1 (random)))
(osc4_phase:SAMPLE (* osc_phase_slop .1 (random)))
(osc1_wt:AudioBuffer* DefaultWaveTable)
(osc2_wt:AudioBuffer* DefaultWaveTable)
(osc3_wt:AudioBuffer* DefaultWaveTable)
(osc4_wt:AudioBuffer* DefaultWaveTable)
(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 #t) ;; 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) ;; 1.0-3.0
(pitch_env_amt:SAMPLE 0.0)
(portamento:SAMPLE 0.0) ;; in millis
(res:SAMPLE 0.0)
(performance_profile:i64 0) ;; high by default
(reso:SAMPLE 0.0))
(lambda (data:NoteData* nargs:i64 dargs:SAMPLE*)
(let ((starttime:i64 (note_starttime data))
(notetime:i64 starttime)
(frequency:SAMPLE (+ (note_frequency data) (* (- (random) 0.5) (note_frequency data) osc_slop 0.05)))
(target_frq:SAMPLE frequency)
(amplitude:SAMPLE (note_amplitude data))
(gate:SAMPLE (note_gate 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)
(adsr1 (adsr_c))
(adsr2 (adsr_c))
(adsr3 (adsr_c))
(adsr4 (dadsr_c))
(adsr1_val 0.0)
(adsr2_val 0.0)
(adsr3_val 0.0)
(adsr4_val:SAMPLE 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_delay mod_env_delay)
(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]* (if (= 0 performance_profile)
(moog_ladder_inlined (i64toi32 filter_type))
(lpf_c)))
(_osc1_phase (+ osc1_phase (* osc_phase_slop .1 (random))))
(_osc2_phase (+ osc2_phase (* osc_phase_slop .1 (random))))
(_osc3_phase (+ osc3_phase (* osc_phase_slop .1 (random))))
(_osc4_phase (+ osc4_phase (* osc_phase_slop .1 (random))))
(sin1 (osc_c _osc1_phase))
(sin2 (osc_c _osc2_phase))
(sin3 (osc_c _osc3_phase))
(sin4 (osc_c _osc4_phase))
(saw1 (blsaw_c _osc1_phase #f #f))
(saw2 (blsaw_c _osc2_phase #f #f))
(saw3 (blsaw_c _osc3_phase #f #f))
(saw4 (blsaw_c _osc4_phase #f #f))
(pulse1 (blpulse_c _osc1_phase #f))
(pulse2 (blpulse_c _osc2_phase #f))
(pulse3 (blpulse_c _osc3_phase #f))
(pulse4 (blpulse_c _osc4_phase #f))
(tri1 (bltri_c _osc1_phase))
(tri2 (bltri_c _osc2_phase))
(tri3 (bltri_c _osc3_phase))
(tri4 (bltri_c _osc4_phase))
(wt1 (AudioBuffer_shared_data osc1_wt))
(wt2 (AudioBuffer_shared_data osc2_wt))
(wt3 (AudioBuffer_shared_data osc3_wt))
(wt4 (AudioBuffer_shared_data osc4_wt))
(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))
(if (= 0 performance_profile) (filter.saturation (clamp filter_saturation 1.0:f 3.0:f)))
(lambda (time:i64 chan:i64)
(if (= chan 0)
(begin
(set! notetime (tref data 7)) ;; look for voice steeling
;; this for voice steeling
(if (and (<> starttime notetime) (>= time notetime))
(begin
;; (println "steeling voice:" (convert (frq2midi frequency) i64) "for" (note_frequency data))
(if (not legato)
(begin
(set! amplitude (note_amplitude data)) ;; reset envelopes
(retrigger_adsr adsr1) (retrigger_adsr adsr2) (retrigger_adsr adsr3) (retrigger_dadsr adsr4)))
;; (note_starttime data (tref data 7))
(set! starttime (tref data 7)) ;(note_starttime data))
(set! target_frq (note_frequency data))
(set! glideinc (/ (- target_frq frequency) (* portamento 0.001 SRf)))
(if (< portamento 0.001) (set! frequency target_frq))
(AudioBuffer_set_phase wt1 0.0)
(AudioBuffer_set_phase wt2 0.0)
(AudioBuffer_set_phase wt3 0.0)
(AudioBuffer_set_phase wt4 0.0)
(set! reltime 0)
(set! gate 1.0) ;(note_gate data))
(set! duration (note_duration data))))
;; voice steeling done
(if (> (fabs (- target_frq frequency)) 0.125) ;; 1/8 hz
(set! frequency (+ frequency glideinc)))
(if (and (> gate 0.5) (> (- time starttime) duration)) (set! gate 0.0))
;; (if (and (> (note_gate data) 0.5) (> (- time starttime) duration)) (note_gate data 0.0)) ;; (set! gate 0.0))
(set! adsr1_val (adsr1 chan gate amp_attack amp_decay amp_sustain amp_release))
(set! adsr2_val (adsr2 chan gate filter_attack filter_decay filter_sustain filter_release))
(set! adsr3_val (adsr3 chan gate pitch_attack pitch_decay 0.0 0.0))
(set! adsr4_val (adsr4 chan gate mod_delay 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 (< gate 0.1) (set! reltime (+ reltime 1)))
(if (> reltime amp_release_samples)
(if (< amp 0.01)
(note_active data #f) ;; stop note if amp less than 0.01
(begin (set! amplitude (- amplitude 0.01)) #t))) ;; otherwise decrease amplitude over max 100 samples
;; setup mod sources
(if (> osc1_amp 0.001)
(set! osc1_out (* (+ osc1_amp (* adsr4_val (aref mods PARAM_OSC1_AMP)))
(cond ((= osc1_wave 0) (sin1 1.0 (+ (* tune1 frq) (* adsr4_val (aref mods PARAM_OSC1_FRQ)))))
((= osc1_wave 1) (saw1 1.0 (+ (* tune1 frq) (* adsr4_val (aref mods PARAM_OSC1_FRQ)))))
((= osc1_wave 2) (pulse1 1.0 (+ (* tune1 frq)
(* adsr4_val (aref mods PARAM_OSC1_FRQ)))
(+ pw1 (* adsr4_val (aref mods PARAM_OSC1_PW)))))
((= osc1_wave 3) (tri1 1.0 (+ (* tune1 frq) (* adsr4_val (aref mods PARAM_OSC1_FRQ)))))
((= osc1_wave 4) (AudioBuffer_read_interp_pw wt1
(+ (* tune1 frq) (* adsr4_val (aref mods PARAM_OSC1_FRQ)))
0
(+ pw1 (* adsr4_val (aref mods PARAM_OSC1_PW)))))
(else zero))))
(set! osc1_out 0.0))
(if (> osc2_amp 0.001)
(set! osc2_out (* (+ osc2_amp (* adsr4_val (aref mods PARAM_OSC2_AMP)))
(cond ((= osc2_wave 0) (sin2 1.0 (+ (* tune2 frq) (* adsr4_val (aref mods PARAM_OSC2_FRQ)))))
((= osc2_wave 1) (saw2 1.0 (+ (* tune2 frq) (* adsr4_val (aref mods PARAM_OSC2_FRQ)))))
((= osc2_wave 2) (pulse2 1.0 (+ (* tune2 frq) (* adsr4_val (aref mods PARAM_OSC2_FRQ)))
(+ pw2 (* adsr4_val (aref mods PARAM_OSC2_PW)))))
((= osc2_wave 3) (tri2 1.0 (+ (* tune2 frq) (* adsr4_val (aref mods PARAM_OSC2_FRQ)))))
((= osc2_wave 4) (AudioBuffer_read_interp_pw wt2
(+ (* tune2 frq) (* adsr4_val (aref mods PARAM_OSC2_FRQ)))
0
(+ pw2 (* adsr4_val (aref mods PARAM_OSC2_PW)))))
(else zero))))
(set! osc2_out 0.0))
(if (> osc3_amp 0.001)
(set! osc3_out (* (+ osc3_amp (* adsr4_val (aref mods PARAM_OSC3_AMP)))
(cond ((= osc3_wave 0) (sin3 1.0 (+ (* tune3 frq) (* adsr4_val (aref mods PARAM_OSC3_FRQ)))))
((= osc3_wave 1) (saw3 1.0 (+ (* tune3 frq) (* adsr4_val (aref mods PARAM_OSC3_FRQ)))))
((= osc3_wave 2) (pulse3 1.0 (+ (* tune3 frq) (* adsr4_val (aref mods PARAM_OSC3_FRQ)))
(+ pw3 (* adsr4_val (aref mods PARAM_OSC3_PW)))))
((= osc3_wave 3) (tri3 1.0 (+ (* tune3 frq) (* adsr4_val (aref mods PARAM_OSC3_FRQ)))))
((= osc3_wave 4) (AudioBuffer_read_interp_pw wt3
(+ (* tune3 frq) (* adsr4_val (aref mods PARAM_OSC3_FRQ)))
0
(+ pw3 (* adsr4_val (aref mods PARAM_OSC3_PW)))))
(else zero))))
(set! osc3_out 0.0))
(if (> osc4_amp 0.001)
(set! osc4_out (* (+ osc4_amp (* adsr4_val (aref mods PARAM_OSC4_AMP)))
(cond ((= osc4_wave 0) (sin4 1.0 (+ (* tune4 frq) (* adsr4_val (aref mods PARAM_OSC4_FRQ)))))
((= osc4_wave 1) (saw4 1.0 (+ (* tune4 frq) (* adsr4_val (aref mods PARAM_OSC4_FRQ)))))
((= osc4_wave 2) (pulse4 1.0 (+ (* tune4 frq) (* adsr4_val (aref mods PARAM_OSC4_FRQ)))
(+ pw4 (* adsr4_val (aref mods PARAM_OSC4_PW)))))
((= osc4_wave 3) (tri4 1.0 (+ (* tune4 frq) (* adsr4_val (aref mods PARAM_OSC4_FRQ)))))
((= osc4_wave 4) (AudioBuffer_read_interp_pw wt4
(+ (* tune4 frq) (* adsr4_val (aref mods PARAM_OSC4_FRQ)))
0
(+ pw4 (* adsr4_val (aref mods PARAM_OSC4_PW)))))
(else zero))))
(set! osc4_out 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
(+ osc1_out
osc2_out
osc3_out
osc4_out
sub_out
noise_out)
cof reso)))))
main_out))))))