Skip to content

Instantly share code, notes, and snippets.

@nattog
Last active May 4, 2022 16:22
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nattog/841bcfb813aefdc751cacf0d4b79f4ab to your computer and use it in GitHub Desktop.
Save nattog/841bcfb813aefdc751cacf0d4b79f4ab to your computer and use it in GitHub Desktop.
Drummer :: sequencer for Monome Crow + Druid
-- drummer
-- 4 track pattern sequencer
-- pattern notation looks like this 'x---x---x---x---'
-- update sequence track with set(track, pattern)
--
-- queue a new sequence
-- progress(seq table, period - by default 16)
--
-- control transport
-- start() stop() reset()
counter = 0 -- used to get index by modulo of seq items
seq = {"", "", "", ""}
pause = false
preset = {'x---', '----x---', '--x-', 'xx--x--'}
queued = {}
wait = 0
function init()
-- set up input modes
input[1].mode("change", 1, 0.1, "rising")
input[2].mode("change", 1, 0.1, "rising")
input[1].change = function() if pause == false then step() end end
input[2].change = reset
-- set up output modes
for i = 1, 4 do
output[i].action = pulse(0.02,8)
end
end
-- resets counter variable to initial value
function reset()
counter = 0
end
-- update counter and trigger for each 'x' found at index of each seq
function step()
local to_print = ""
for chan = 1, #seq do
if chan <= 4 then
if #seq[chan] > 0 then
local step_idx = math.floor(counter % #seq[chan]) + 1
local step_value = seq[chan]:sub(step_idx, step_idx)
if step_value == 'x' then
output[chan]()
end
to_print = to_print .. (step_value == 'x' and step_value or "_") .. " "
else
to_print = to_print .. "_ "
end
end
end
-- increments counter
counter = counter + 1
if #queued > 0 then
-- countdown wait if queue has elements
if wait > 0 then
wait = wait - 1
else
-- can set the queue
seq = queued
wait = 0
queued = {}
end
end
print(to_print)
end
function set(idx, val)
-- sets all tracks to same val
local to_print = ''
if idx == "*" then
for i = 1, #seq do
seq[i] = #val > 0 and val or ''
to_print = 'SET ALL TO ' .. string.upper(seq[1])
end
-- only set sequences for valid output indexes
elseif idx < 5 and idx > 0 then
seq[idx] = #val > 0 and val or ''
to_print = 'SET ' .. idx .. ' TO ' .. string.upper(seq[idx]);
end
print('\n' .. to_print .. '\n')
end
function stop()
pause = true
end
function start()
pause = false
end
function progress(tab, period)
local progress_on = period or 16
if tab == nil then
print('no input')
return
end
-- if input is empty table, set all channels to empty strings
local new_seq = #tab < 1 and {"", "", "", ""} or table.shallow_copy(tab)
-- if running then a wait period is necessary
if pause == false then
wait_period = progress_on % counter
-- add seq to queue
if wait_period ~= 0 then
queued = new_seq
wait = wait_period
else
seq = new_seq
end
else
-- update seq
seq = new_seq
reset()
end
end
function table.shallow_copy(t)
local t2 = {}
for k,v in pairs(t) do
t2[k] = v
end
return t2
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment