-- teach the musicator -- uses samples from: https://magenta.tensorflow.org/datasets/maestro#v300 --require("luarocks.loader") --require("luamidi") require("./musicator") local inspect = require("inspect") math.randomseed(os.time()) function flatten(v) local res = {} local function flatten(v) if type(v) ~= "table" then table.insert(res, v) return end for _, v in ipairs(v) do flatten(v) end end flatten(v) return res end local training_data = { -- simple ascending phrase { "C-4","...","D-4","...","E-4","...","G-4","...", "E-4","...","D-4","...","C-4","...","...","..." }, -- descending answer { "G-4","...","F-4","...","E-4","...","D-4","...", "C-4","...","D-4","...","E-4","...","...","..." }, -- arpeggio major { "C-4","...","E-4","...","G-4","...","C-5","...", "G-4","...","E-4","...","C-4","...","...","..." }, -- arpeggio minor { "A-4","...","C-5","...","E-5","...","A-5","...", "E-5","...","C-5","...","A-4","...","...","..." }, -- stepwise melody (folk-like) { "D-4","...","E-4","...","F-4","...","G-4","...", "F-4","...","E-4","...","D-4","...","...","..." }, -- repeated note rhythm { "C-5","C-5","...","C-5","...","C-5","C-5","...", "D-5","...","E-5","...","...","...","...","..." }, -- bounce pattern { "C-5","...","G-4","...","C-5","...","G-4","...", "D-5","...","A-4","...","D-5","...","...","..." }, -- scale run up { "C-4","D-4","E-4","F-4","G-4","A-4","B-4","C-5", "...","...","...","...","...","...","...","..." }, -- scale run down { "C-5","B-4","A-4","G-4","F-4","E-4","D-4","C-4", "...","...","...","...","...","...","...","..." }, -- syncopated feel { "C-5","...","...","D-5","...","...","E-5","...", "C-5","...","...","G-4","...","...","...","..." }, -- triplet-ish feel (simulated) { "E-5","D-5","C-5","...","E-5","D-5","C-5","...", "G-4","...","...","...","...","...","...","..." }, -- small jumps { "C-5","...","E-5","...","D-5","...","F-5","...", "E-5","...","C-5","...","...","...","...","..." }, -- call { "G-4","...","A-4","...","C-5","...","A-4","...", "...","...","...","...","...","...","...","..." }, -- response { "E-4","...","F-4","...","G-4","...","F-4","...", "D-4","...","...","...","...","...","...","..." }, -- denser pattern (DDR-like) { "C-5","D-5","E-5","...","D-5","E-5","F-5","...", "E-5","D-5","C-5","...","...","...","...","..." }, -- alternating pattern (good for gameplay) { "C-5","...","E-5","...","C-5","...","E-5","...", "D-5","...","F-5","...","D-5","...","...","..." }, -- higher register variant { "G-5","...","A-5","...","B-5","...","D-6","...", "B-5","...","A-5","...","G-5","...","...","..." }, -- low register grounding { "C-4","...","G-3","...","C-4","...","G-3","...", "F-3","...","C-4","...","...","...","...","..." }, -- variant of ascending with offset { "...","C-4","...","D-4","...","E-4","...","G-4", "...","E-4","...","D-4","...","C-4","...","..." }, -- staggered rhythm { "C-4","...","...","D-4","...","E-4","...","...", "G-4","...","E-4","...","D-4","...","...","..." }, -- broken arpeggio (different spacing) { "C-4","E-4","...","G-4","...","C-5","...", "G-4","E-4","...","C-4","...","...","...","..." }, -- minor variation (shifted) { "...","A-4","C-5","...","E-5","...","A-5","...", "E-5","...","C-5","...","A-4","...","...","..." }, -- repeated + variation { "D-4","D-4","...","E-4","...","F-4","F-4","...", "G-4","...","F-4","...","E-4","...","...","..." }, -- zig-zag motion { "C-5","...","E-5","...","D-5","...","F-5","...", "E-5","...","G-5","...","F-5","...","...","..." }, -- alternating step/jump { "C-5","...","D-5","...","G-5","...","F-5","...", "E-5","...","C-5","...","D-5","...","...","..." }, -- denser burst pattern { "C-5","D-5","E-5","F-5","...","E-5","D-5","C-5", "...","...","...","...","...","...","...","..." }, -- rolling pattern { "E-5","...","D-5","...","C-5","...","D-5","...", "E-5","...","G-5","...","E-5","...","...","..." }, -- syncopation variant { "...","C-5","...","...","E-5","...","...","G-5", "...","E-5","...","C-5","...","...","...","..." }, -- low-high interplay { "C-4","...","G-4","...","C-5","...","G-4","...", "E-4","...","C-4","...","...","...","...","..." }, -- descending but staggered { "C-5","...","...","B-4","...","A-4","...","...", "G-4","...","F-4","...","E-4","...","...","..." }, -- small trill-like feel { "E-5","F-5","E-5","...","E-5","F-5","E-5","...", "D-5","...","C-5","...","...","...","...","..." }, -- call variant (shifted timing) { "...","G-4","...","A-4","...","C-5","...","A-4", "...","...","...","...","...","...","...","..." }, -- response variant { "...","E-4","...","F-4","...","G-4","...","F-4", "D-4","...","...","...","...","...","...","..." }, -- dense DDR-ish alternating { "C-5","...","D-5","...","C-5","...","D-5","...", "E-5","...","F-5","...","E-5","...","...","..." }, -- higher variation arpeggio { "G-5","...","B-5","...","D-6","...","G-6","...", "D-6","...","B-5","...","G-5","...","...","..." }, -- low groove pattern { "C-3","...","C-4","...","G-3","...","C-4","...", "F-3","...","C-4","...","...","...","...","..." }, -- slightly chaotic (good for branching) { "C-5","...","E-5","D-5","...","G-5","...","F-5", "...","D-5","...","C-5","...","...","...","..." }, -- mixed density { "C-5","D-5","...","E-5","...","F-5","G-5","...", "E-5","...","D-5","C-5","...","...","...","..." }, -- offset staircase up { "...","C-4","D-4","E-4","F-4","G-4","A-4","B-4", "C-5","...","...","...","...","...","...","..." }, -- offset staircase down { "...","C-5","B-4","A-4","G-4","F-4","E-4","D-4", "C-4","...","...","...","...","...","...","..." }, -- dense zigzag { "C-5","E-5","D-5","F-5","E-5","G-5","F-5","A-5", "G-5","...","...","...","...","...","...","..." }, -- jack pattern (DDR classic) { "C-5","C-5","C-5","...","C-5","C-5","...","...", "D-5","D-5","...","...","...","...","...","..." }, -- alternating two-note burst { "C-5","D-5","C-5","D-5","C-5","D-5","...","...", "E-5","F-5","E-5","F-5","...","...","...","..." }, -- wide jumps { "C-4","...","G-5","...","D-4","...","A-5","...", "E-4","...","B-5","...","...","...","...","..." }, -- rolling triplet-ish { "C-5","E-5","G-5","...","E-5","C-5","E-5","...", "G-5","...","...","...","...","...","...","..." }, -- syncopated dense { "...","C-5","D-5","...","E-5","...","F-5","G-5", "...","E-5","...","C-5","...","...","...","..." }, -- mirrored pattern { "C-5","D-5","E-5","F-5","E-5","D-5","C-5","...", "...","...","...","...","...","...","...","..." }, -- chord-outline arpeggio feel { "C-4","...","G-4","...","E-5","...","G-4","...", "C-4","...","...","...","...","...","...","..." }, -- broken rhythm variant { "C-5","...","D-5","E-5","...","F-5","...","G-5", "E-5","...","D-5","...","C-5","...","...","..." }, -- fast burst then rest { "C-5","D-5","E-5","F-5","G-5","A-5","...","...", "...","...","...","...","...","...","...","..." }, -- low-high bounce fast { "C-3","C-5","C-3","C-5","C-3","C-5","...","...", "G-3","G-5","G-3","G-5","...","...","...","..." }, -- repeated with shift { "...","E-5","...","E-5","...","E-5","...","...", "D-5","...","C-5","...","...","...","...","..." }, -- clustered mid { "D-5","E-5","F-5","...","E-5","D-5","C-5","...", "D-5","...","...","...","...","...","...","..." }, -- broken descending { "C-6","...","A-5","...","F-5","...","D-5","...", "C-5","...","...","...","...","...","...","..." }, -- chaotic jumpy (important for branching) { "C-5","...","F-5","D-5","...","A-5","...","E-5", "...","G-5","...","C-5","...","...","...","..." }, -- double-step pattern { "C-5","D-5","D-5","E-5","E-5","F-5","...","...", "G-5","...","...","...","...","...","...","..." }, -- uneven spacing { "C-5","...","...","D-5","E-5","...","...","F-5", "G-5","...","...","...","...","...","...","..." }, -- fast alternating high { "G-5","A-5","G-5","A-5","G-5","A-5","...","...", "F-5","E-5","...","...","...","...","...","..." }, -- low groove with variation { "C-3","...","C-4","...","G-3","...","D-4","...", "F-3","...","C-4","...","...","...","...","..." }, -- semi-random filler (very useful) { "C-5","...","E-5","...","D-5","...","G-5","...", "F-5","...","A-5","...","E-5","...","...","..." }, -- near-repetition (state collision booster) { "C-5","...","D-5","...","E-5","...","C-5","...", "D-5","...","E-5","...","C-5","...","...","..." }, -- same but shifted (VERY important) { "...","C-5","...","D-5","...","E-5","...","C-5", "...","D-5","...","E-5","...","C-5","...","..." }, } local model = build_markov_model(flatten(training_data), 2) print(inspect(model)) --[[ local generated = generate_sequence(model, 100) for i,v in ipairs(generated) do print(v) end --]]