seaaaaa
| -- seaaaaa with no screen | |
| -- | |
| -- subtractive polysynth with 5 patterns | |
| -- controlled by midi or grid | |
| -- | |
| -- grid pattern player: | |
| -- 1 1 record toggle | |
| -- 1 2 play toggle | |
| -- 1 3-7 pattern selectors | |
| -- 1 8 transpose mode | |
| local tab = require 'tabutil' | |
| local pattern_time = require 'pattern_time' | |
| local selectedPattern = 1 | |
| local mode_transpose = {0, 0, 0, 0, 0} | |
| local root = {{ x=5, y=5 }, { x=5, y=5 }, { x=5, y=5 }, { x=5, y=5 }, { x=5, y=5 }} | |
| local trans = {{ x=5, y=5 }, { x=5, y=5 }, { x=5, y=5 }, { x=5, y=5 }, { x=5, y=5 }} | |
| local lit = {{}, {}, {}, {}, {}} | |
| engine.name = 'PolySub' | |
| -- pythagorean minor/major, kinda | |
| local ratios = { 1, 9/8, 6/5, 5/4, 4/3, 3/2, 27/16, 16/9 } | |
| local base = 27.5 -- low A | |
| local function getHz(deg,oct) | |
| return base * ratios[deg] * (2^oct) | |
| end | |
| local function getHzET(note) | |
| return 55*2^(note/12) | |
| end | |
| -- current count of active voices | |
| local nvoices = {0, 0, 0, 0, 0} | |
| function init() | |
| pat = {pattern_time.new(), pattern_time.new(), pattern_time.new(), pattern_time.new(), pattern_time.new()} | |
| pat[1].process = grid_note_trans | |
| pat[2].process = grid_note_trans | |
| pat[3].process = grid_note_trans | |
| pat[4].process = grid_note_trans | |
| pat[5].process = grid_note_trans | |
| params:add_control("shape", controlspec.new(0,1,"lin",0,0,"")) | |
| params:set_action("shape", function(x) engine.shape(x) end) | |
| params:add_control("timbre", controlspec.new(0,1,"lin",0,0.5,"")) | |
| params:set_action("timbre", function(x) engine.timbre(x) end) | |
| params:add_control("noise", controlspec.new(0,1,"lin",0,0,"")) | |
| params:set_action("noise", function(x) engine.noise(x) end) | |
| params:add_control("cut", controlspec.new(0,32,"lin",0,8,"")) | |
| params:set_action("cut", function(x) engine.cut(x) end) | |
| params:add_control("fgain", controlspec.new(0,6,"lin",0,0,"")) | |
| params:set_action("fgain", function(x) engine.fgain(x) end) | |
| params:add_control("cutEnvAmt", controlspec.new(0,1,"lin",0,0,"")) | |
| params:set_action("cutEnvAmt", function(x) engine.cutEnvAmt(x) end) | |
| params:add_control("detune", controlspec.new(0,1,"lin",0,0,"")) | |
| params:set_action("detune", function(x) engine.detune(x) end) | |
| params:add_control("ampAtk", controlspec.new(0.01,10,"lin",0,0.05,"")) | |
| params:set_action("ampAtk", function(x) engine.ampAtk(x) end) | |
| params:add_control("ampDec", controlspec.new(0,2,"lin",0,0.1,"")) | |
| params:set_action("ampDec", function(x) engine.ampDec(x) end) | |
| params:add_control("ampSus", controlspec.new(0,1,"lin",0,1,"")) | |
| params:set_action("ampSus", function(x) engine.ampSus(x) end) | |
| params:add_control("ampRel", controlspec.new(0.01,10,"lin",0,1,"")) | |
| params:set_action("ampRel", function(x) engine.ampRel(x) end) | |
| params:add_control("cutAtk", controlspec.new(0.01,10,"lin",0,0.05,"")) | |
| params:set_action("cutAtk", function(x) engine.cutAtk(x) end) | |
| params:add_control("cutDec", controlspec.new(0,2,"lin",0,0.1,"")) | |
| params:set_action("cutDec", function(x) engine.cutDec(x) end) | |
| params:add_control("cutSus", controlspec.new(0,1,"lin",0,1,"")) | |
| params:set_action("cutSus", function(x) engine.cutSus(x) end) | |
| params:add_control("cutRel", controlspec.new(0.01,10,"lin",0,1,"")) | |
| params:set_action("cutRel", function(x) engine.cutRel(x) end) | |
| engine.level(0.05) | |
| engine.stopAll() | |
| params:read("tehn/earthsea.pset") | |
| params:bang() | |
| if g then gridredraw() end | |
| end | |
| function gridkey(x, y, z) | |
| if x == 1 then | |
| if z == 1 then | |
| if y == 1 and pat[selectedPattern].rec == 0 then | |
| mode_transpose[selectedPattern] = 0 | |
| trans[selectedPattern].x = 5 | |
| trans[selectedPattern].y = 5 | |
| pat[selectedPattern]:stop() | |
| pat[selectedPattern]:clear() | |
| pat[selectedPattern]:rec_start() | |
| elseif y == 1 and pat[selectedPattern].rec == 1 then | |
| pat[selectedPattern]:rec_stop() | |
| if pat[selectedPattern].count > 0 then | |
| root[selectedPattern].x = pat[selectedPattern].event[1].x | |
| root[selectedPattern].y = pat[selectedPattern].event[1].y | |
| trans[selectedPattern].x = root[selectedPattern].x | |
| trans[selectedPattern].y = root[selectedPattern].y | |
| pat[selectedPattern]:start() | |
| end | |
| elseif y == 2 and pat[selectedPattern].play == 0 and pat[selectedPattern].count > 0 then | |
| if pat[selectedPattern].rec == 1 then | |
| pat[selectedPattern]:rec_stop() | |
| end | |
| pat[selectedPattern]:start() | |
| elseif y == 2 and pat[selectedPattern].play == 1 then | |
| pat[selectedPattern]:stop() | |
| nvoices[selectedPattern] = 0 | |
| lit[selectedPattern] = {} | |
| elseif y >= 3 and y <= 7 then | |
| selectedPattern = y - 2 | |
| elseif y == 8 then | |
| mode_transpose[selectedPattern] = 1 - mode_transpose[selectedPattern] | |
| end | |
| end | |
| else | |
| if mode_transpose[selectedPattern] == 0 then | |
| local e = {} | |
| e.id = x*8 + y | |
| e.x = x | |
| e.y = y | |
| e.state = z | |
| e.selectedPattern = selectedPattern | |
| pat[selectedPattern]:watch(e) | |
| grid_note(e) | |
| else | |
| trans[selectedPattern].x = x | |
| trans[selectedPattern].y = y | |
| end | |
| end | |
| gridredraw() | |
| end | |
| function grid_note(e) | |
| local note = ((7-e.y)*5) + e.x | |
| if e.state > 0 then | |
| if nvoices[selectedPattern] < 6 then | |
| engine.start(e.id, getHzET(note)) | |
| lit[selectedPattern][e.id] = {} | |
| lit[selectedPattern][e.id].x = e.x | |
| lit[selectedPattern][e.id].y = e.y | |
| nvoices[selectedPattern] = nvoices[selectedPattern] + 1 | |
| end | |
| else | |
| if lit[selectedPattern][e.id] ~= nil then | |
| engine.stop(e.id) | |
| lit[selectedPattern][e.id] = nil | |
| nvoices[selectedPattern] = nvoices[selectedPattern] - 1 | |
| end | |
| end | |
| gridredraw() | |
| end | |
| function grid_note_trans(e) | |
| local note = ((7-e.y+(root[e.selectedPattern].y-trans[e.selectedPattern].y))*5) + e.x + (trans[e.selectedPattern].x-root[e.selectedPattern].x) | |
| if e.state > 0 then | |
| if nvoices[e.selectedPattern] < 6 then | |
| engine.start(e.id, getHzET(note)) | |
| lit[e.selectedPattern][e.id] = {} | |
| lit[e.selectedPattern][e.id].x = e.x + trans[e.selectedPattern].x - root[e.selectedPattern].x | |
| lit[e.selectedPattern][e.id].y = e.y + trans[e.selectedPattern].y - root[selectedPattern].y | |
| nvoices[e.selectedPattern] = nvoices[e.selectedPattern] + 1 | |
| end | |
| else | |
| engine.stop(e.id) | |
| lit[e.selectedPattern][e.id] = nil | |
| nvoices[e.selectedPattern] = nvoices[e.selectedPattern] - 1 | |
| end | |
| gridredraw() | |
| end | |
| function gridredraw() | |
| g:all(0) | |
| g:led(1,1,2 + pat[selectedPattern].rec * 10) | |
| g:led(1,2,2 + pat[selectedPattern].play * 10) | |
| for y=3,7 do | |
| if selectedPattern + 2 == y then | |
| g:led(1,y,12) | |
| end | |
| end | |
| g:led(1,8,2 + mode_transpose[selectedPattern] * 10) | |
| if mode_transpose[selectedPattern] == 1 then g:led(trans[selectedPattern].x, trans[selectedPattern].y, 4) end | |
| for i,e in pairs(lit[selectedPattern]) do | |
| g:led(e.x, e.y,15) | |
| end | |
| g:refresh() | |
| end | |
| function cleanup() | |
| stop_all_screen_notes() | |
| pat[1]:stop() | |
| pat[2]:stop() | |
| pat[3]:stop() | |
| pat[4]:stop() | |
| pat[5]:stop() | |
| pat[1] = nil | |
| pat[2] = nil | |
| pat[3] = nil | |
| pat[4] = nil | |
| pat[5] = nil | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment