(local pxl8 (require :pxl8)) (var time 0) (var step 0) (var ctx nil) (var params nil) (var bass-params nil) (var playing false) (local bpm 120) (local beat (/ 60 bpm)) (local whole (* 4 beat)) (local half (* 2 beat)) (local quarter beat) (local eighth (/ beat 2)) (local sixteenth (/ beat 4)) (local melody [[60 eighth] [64 eighth] [67 eighth] [72 eighth] [67 eighth] [64 eighth] [60 eighth] [64 eighth] [67 eighth] [72 eighth] [76 eighth] [72 eighth] [67 eighth] [64 eighth] [62 eighth] [66 eighth] [69 eighth] [74 eighth] [69 eighth] [66 eighth] [62 eighth] [66 eighth] [69 eighth] [74 eighth] [78 eighth] [74 eighth] [69 eighth] [66 eighth]]) ; (local bass [[36 half] [40 half] [36 half] [38 half] ; [38 half] [36 half] [40 half] [38 half]]) (local step-duration eighth) (fn init [] (set ctx (pxl8.sfx_context_create)) (local delay (pxl8.sfx_delay_create {:time_l 350 :time_r 500 :feedback 0.6 :mix 0.2})) (local reverb (pxl8.sfx_reverb_create {:room 0.25 :damping 0.5 :mix 0.5})) (local compressor (pxl8.sfx_compressor_create {:threshold -12 :ratio 4 :attack 10 :release 100})) (pxl8.sfx_context_append_node ctx delay) (pxl8.sfx_context_append_node ctx reverb) (pxl8.sfx_context_append_node ctx compressor) (pxl8.sfx_mixer_attach ctx) (set params (pxl8.sfx_voice_params {:waveform pxl8.SFX_WAVE_TRIANGLE :attack 0.01 :decay 0.25 :sustain 0.0 :release 0.01 :filter_type pxl8.SFX_FILTER_LOWPASS :filter_cutoff 2500 :filter_resonance 0.05 :filter_attack 0.05 :filter_decay 0.1 :filter_sustain 0.2 :filter_release 0.05 :filter_env_depth 1500 :fx_send 0.7}))) ; (set bass-params (pxl8.sfx_voice_params ; {:waveform pxl8.SFX_WAVE_SAW ; :attack 0.02 :decay 0.3 :sustain 0.6 :release 0.4 ; :filter_type pxl8.SFX_FILTER_LOWPASS ; :filter_attack 0.02 :filter_decay 0.3 :filter_sustain 0.6 :filter_release 0.4 ; :filter_cutoff 90 :filter_resonance 0.25 ; :fx_send 0.2}))) (fn start [] (set playing true) (set time 0) (set step 0)) (fn stop [] (set playing false) (pxl8.sfx_stop_all ctx)) (fn update [dt] (when playing (set time (+ time dt)) (when (>= time step-duration) (set time (- time step-duration)) (local melody-entry (. melody (+ 1 (% step (length melody))))) (local note (. melody-entry 1)) (local dur (. melody-entry 2)) (pxl8.sfx_play_note ctx note params 0.4 dur) ; (when (= (% step 4) 0) ; (local bass-idx (+ 1 (% (math.floor (/ step 4)) (length bass)))) ; (local bass-entry (. bass bass-idx)) ; (local bass-note (. bass-entry 1)) ; (local bass-dur (. bass-entry 2)) ; (pxl8.sfx_play_note ctx bass-note bass-params 0.35 bass-dur)) (set step (+ step 1))))) {:init init :start start :stop stop :update update :is-playing (fn [] playing)}