Created
January 23, 2023 16:02
-
-
Save schollz/e2cc49425d54336b422e144e7eeb34cc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- melody generator | |
engine.name="PolyPerc" | |
musicutil=require("musicutil") | |
function init() | |
engine.release(2) | |
engine.amp(0.3) | |
local chords={"I","vi","IV","iii"} -- change to any chords | |
local movement_left=6 -- change to 0-12 | |
local movement_right=6 -- change to 0-12 | |
local stay_on_chord=0.95 -- change to 0-1 | |
play(chords,1,movement_left,movement_right,stay_on_chord) | |
end | |
function play(chord_structure,factor,move_left,move_right,stay_scale) | |
stay_scale=util.clamp(stay_scale,0,1) | |
-- notes to play | |
local notes_to_play={} | |
-- generate chords | |
local chords={} | |
for i,v in ipairs(chord_structure) do | |
local scale=musicutil.generate_scale(12,1,8) | |
local chord_notes=musicutil.generate_chord_roman(12,1,v) | |
local notes_in_chord={} | |
for _,u in ipairs(chord_notes) do | |
notes_in_chord[u]=true | |
for j=1,8 do | |
notes_in_chord[u+(12*j)]=true | |
end | |
end | |
local note_start=72 | |
for jj=1,4*factor do | |
-- find note_start in scale | |
local notes_to_choose={} | |
for _,note in ipairs(scale) do | |
if note>note_start-move_left and note<note_start+move_right then | |
table.insert(notes_to_choose,note) | |
end | |
end | |
local weights={} | |
local scale_size=#notes_to_choose | |
for i,note in ipairs(notes_to_choose) do | |
weights[i]=notes_in_chord[note]~=nil and scale_size or scale_size*(1-stay_scale) | |
-- weights[i]=weights[i]+(scale_size-i) | |
end | |
local note_next=choose_with_weights(notes_to_choose,weights) | |
table.insert(notes_to_play,note_next) | |
note_start=note_next | |
end | |
end | |
local notei=0 | |
local note_last=0 | |
clock.run(function() | |
while true do | |
clock.sync(1/factor) | |
notei=(notei)%#notes_to_play+1 | |
local note_next=notes_to_play[notei] | |
if note_next~=note_last then | |
engine.hz(musicutil.note_num_to_freq(note_next)) | |
end | |
note_last=note_next | |
end | |
end) | |
end | |
function choose_with_weights(choices,weights) | |
local totalWeight=0 | |
for _,weight in pairs(weights) do | |
totalWeight=totalWeight+weight | |
end | |
local rand=math.random()*totalWeight | |
local choice=nil | |
for i,weight in pairs(weights) do | |
if rand<weight then | |
choice=choices[i] | |
break | |
else | |
rand=rand-weight | |
end | |
end | |
return choice | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment