;; ============================================================================ ;; Theme in A minor ;; Key: Am | Tempo: 95 BPM | Time: 4/4 ;; ============================================================================ ;; ;; Melody (Triangle, A4 range): ;; Bar 1: A4~ .C5 | E5 D5 | C5 A4 | G4 A4 | ;; Bar 2: A4~ .C5 | E5 G5 | F5 E5 | D5~~~~ | ;; Bar 3: D5~ .E5 | F5 D5 | C5 A4 | G4 A4 | ;; Bar 4: C5~ .D5 | E5 C5 | A4 G4 | A4~~~~ | ;; ;; Bass (Triangle, A2 range, octave jumps): ;; | A2 A2 A3 A2 | A2 A3 A2 A3 | C3 C3 C4 C3 | C3 C4 C3 C4 | ;; | D3 D3 D4 D3 | D3 D4 D3 D4 | A2 A2 A3 A2 | A2 A3 E3 A2 | ;; ;; Legend: ~ = held note, . = sixteenth rest before ;; ============================================================================ (local pxl8 (require :pxl8)) (var time 0) (var step 0) (var ctx nil) (var melody-params nil) (var bass-params nil) (var playing false) (local bpm 95) (local beat (/ 60 bpm)) (local sixteenth (/ beat 4)) (local eighth (/ beat 2)) (local quarter beat) (local _whole (* 4 beat)) (local melody [[69 eighth] [0 sixteenth] [72 sixteenth] [76 eighth] [74 eighth] [72 eighth] [69 eighth] [67 eighth] [69 eighth] [69 eighth] [0 sixteenth] [72 sixteenth] [76 eighth] [79 eighth] [77 eighth] [76 eighth] [74 quarter] [74 eighth] [0 sixteenth] [76 sixteenth] [77 eighth] [74 eighth] [72 eighth] [69 eighth] [67 eighth] [69 eighth] [72 eighth] [0 sixteenth] [74 sixteenth] [76 eighth] [72 eighth] [69 eighth] [67 eighth] [69 quarter]]) (local bass [[45 eighth] [45 eighth] [57 eighth] [45 eighth] [45 eighth] [57 eighth] [45 eighth] [57 eighth] [48 eighth] [48 eighth] [60 eighth] [48 eighth] [48 eighth] [60 eighth] [48 eighth] [60 eighth] [50 eighth] [50 eighth] [62 eighth] [50 eighth] [50 eighth] [62 eighth] [50 eighth] [62 eighth] [45 eighth] [45 eighth] [57 eighth] [45 eighth] [45 eighth] [57 eighth] [52 eighth] [45 eighth]]) (local step-duration sixteenth) (fn init [] (set ctx (pxl8.sfx_context_create)) (local reverb (pxl8.sfx_reverb_create {:room 0.5 :damping 0.4 :mix 0.35})) (local compressor (pxl8.sfx_compressor_create {:threshold -18 :ratio 6 :attack 3 :release 100})) (pxl8.sfx_context_append_node ctx reverb) (pxl8.sfx_context_append_node ctx compressor) (pxl8.sfx_mixer_attach ctx) (set melody-params (pxl8.sfx_voice_params {:waveform pxl8.SFX_WAVE_TRIANGLE :attack 0.02 :decay 0.15 :sustain 0.5 :release 0.15 :filter_type pxl8.SFX_FILTER_LOWPASS :filter_cutoff 4000 :filter_resonance 0.0 :fx_send 0.4})) (set bass-params (pxl8.sfx_voice_params {:waveform pxl8.SFX_WAVE_TRIANGLE :attack 0.015 :decay 0.1 :sustain 0.7 :release 0.1 :filter_type pxl8.SFX_FILTER_LOWPASS :filter_cutoff 1800 :filter_resonance 0.0 :fx_send 0.15}))) (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-idx (+ 1 (% step (length melody)))) (local melody-entry (. melody melody-idx)) (local melody-note (. melody-entry 1)) (local melody-dur (. melody-entry 2)) (when (> melody-note 0) (pxl8.sfx_play_note ctx melody-note melody-params 0.45 melody-dur)) (local bass-step (math.floor (/ step 2))) (local bass-idx (+ 1 (% bass-step (length bass)))) (local bass-entry (. bass bass-idx)) (local bass-note (. bass-entry 1)) (local bass-dur (. bass-entry 2)) (when (= (% step 2) 0) (pxl8.sfx_play_note ctx bass-note bass-params 0.55 bass-dur)) (set step (+ step 1))))) {:init init :start start :stop stop :update update :is-playing (fn [] playing)}