Skip to content

Instantly share code, notes, and snippets.

@carltesta
Last active September 1, 2018 14:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carltesta/ac0aa240da6fbd7d3981d8cacaa770dc to your computer and use it in GitHub Desktop.
Save carltesta/ac0aa240da6fbd7d3981d8cacaa770dc to your computer and use it in GitHub Desktop.
GENMDM Genesis MIDI Sequencer using Norns (10-track MIDI Sequencer)
-- GENMDM
--
-- step sequencing the genesis
--
-- enc 1 = hp volume
-- enc 2 = select step
-- enc 3 = tune step
-- key 2 = random/linear seq toggle
-- key 3 = clear sequence
-- key 1 = alt
-- alt key 2 = set current step to 0
-- alt key 3 = turn sequence off
-- alt enc 1 = select channel
-- alt enc 2 = populate sequence with random pitches
-- alt enc 3 = change seq length
--
-- GENMDM interface by @little-scale
-- lua script by @carltesta
randVal = {0,0,0,0,0,0,0,0,0,0}
onVal = {1,1,1,1,1,1,1,1,1,1}
alt = false
chanSelect = 1
local audio = require 'audio'
local o = midi.connect(1)
tracks = {one, two, three, four, five, six, seven, eight, nine, ten}
for i=1,10 do tracks[i] = {
on = true,
random = false,
length = 16,
sliders = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
edit = 0,
accum = 1,
step = 0
}
end
midinotes = {"off", "a1", "a#1", "b1", "c1", "c#1", "d1", "d#1", "e1", "f1", "f#1", "g1", "g#1", "a2", "a#2", "b2", "c2", "c#2", "d2", "d#2", "e2", "f2", "f#2", "g2", "g#2", "a3", "a#3", "b3", "c3", "c#3", "d3", "d#3", "e3"}
tracknames = {"YM2612 FM1", "YM2612 FM2", "YM2612 FM3", "YM2612 FM4", "YM2612 FM5", "YM2612 FM6", "SN76489 PSG 1", "SN76489 PSG 2", "SN76489 PSG 3", "SN76489 Noise"}
basenote = {44,44,44,44,44,44,44,44,44,44}
local k = metro[1]
k.count = -1
k.time = 15/72
k.callback = function(stage)
for i=1,10 do
if tracks[i].on == true then
if tracks[i].sliders[tracks[i].step+1]==0 then
o.note_off(tracks[i].sliders[tracks[i].step+1]+basenote[i],0,i)
end
if tracks[i].sliders[tracks[i].step+1]~=0 then
o.note_on(tracks[i].sliders[tracks[i].step+1]+basenote[i],127,i)
end
if tracks[i].random == false then
tracks[i].step = (tracks[i].step + 1) % tracks[i].length
end
if tracks[i].random == true then
tracks[i].step = math.random(tracks[i].length)-1
end
end
if tracks[i].on == false then
redraw()
end
end
redraw()
end
-- parameters below are specific to GENMDM but could be customised to fit any particular MIDI setup
function init()
print("GENMDM: sequencer")
audio.monitor_on()
params:add_number("tempo",20,240,72)
params:set_action("tempo", function(x) k.time = 15/x end)
params:add_separator()
params:add_control("LFO Enable", controlspec.new(1,2,'lin',1,1))
params:set_action("LFO Enable", function(x) o.cc(74,x*64,1) end)
params:add_control("LFO Speed", controlspec.new(1,8,'lin',1,1))
params:set_action("LFO Speed", function(x) o.cc(1,x*16,1) end)
params:add_separator()
--params:add_control("ch:1 preset",controlspec.new(0,16,'lin',1,0))
--params:set_action("ch:1 preset", function(x) sendCC(1,9,x*8) end)
for i=1,10 do
params:add_number("ch:"..i.." octave",1,9,4)
params:set_action("ch:"..i.." octave", function(x) basenote[i] = 12*x-4 end)
end
for i=1,6 do
params:add_control("ch:"..i.." algorithm",controlspec.new(1,8,'lin',1,1))
params:set_action("ch:"..i.." algorithm", function(x) o.cc(14,x*16,i) end)
params:add_control("ch:"..i.." feedback",controlspec.new(1,8,'lin',1,1))
params:set_action("ch:"..i.." feedback", function(x) o.cc(15,x*16,i) end)
params:add_control("ch:"..i.." freq mod",controlspec.new(1,8,'lin',1,1))
params:set_action("ch:"..i.." freq mod", function(x) o.cc(75,x*16,i) end)
params:add_control("ch:"..i.." OP1 level",controlspec.new(1,128,'lin',1,16))
params:set_action("ch:"..i.." OP1 level", function(x) o.cc(16,x,i) end)
params:add_control("ch:"..i.." OP2 level",controlspec.new(1,128,'lin',1,32))
params:set_action("ch:"..i.." OP2 level", function(x) o.cc(17,x,i) end)
params:add_control("ch:"..i.." OP3 level",controlspec.new(1,128,'lin',1,64))
params:set_action("ch:"..i.." OP3 level", function(x) o.cc(18,x,i) end)
params:add_control("ch:"..i.." OP4 level",controlspec.new(1,128,'lin',1,128))
params:set_action("ch:"..i.." OP4 level", function(x) o.cc(19,x,i) end)
params:add_control("ch:"..i.." OP1 multiple",controlspec.new(1,16,'lin',1,1))
params:set_action("ch:"..i.." OP1 multiple", function(x) o.cc(20,x*8,i) end)
params:add_control("ch:"..i.." OP2 multiple",controlspec.new(1,16,'lin',1,1))
params:set_action("ch:"..i.." OP2 multiple", function(x) o.cc(21,x*8,i) end)
params:add_control("ch:"..i.." OP3 multiple",controlspec.new(1,16,'lin',1,1))
params:set_action("ch:"..i.." OP3 multiple", function(x) o.cc(22,x*8,i) end)
params:add_control("ch:"..i.." OP4 multiple",controlspec.new(1,16,'lin',1,1))
params:set_action("ch:"..i.." OP4 multiple", function(x) o.cc(23,x*8,i) end)
params:add_control("ch:"..i.." OP1 attack",controlspec.new(1,32,'lin',1,16))
params:set_action("ch:"..i.." OP1 attack", function(x) o.cc(43,x*4,i) end)
params:add_control("ch:"..i.." OP2 attack",controlspec.new(1,32,'lin',1,16))
params:set_action("ch:"..i.." OP2 attack", function(x) o.cc(44,x*4,i) end)
params:add_control("ch:"..i.." OP3 attack",controlspec.new(1,32,'lin',1,16))
params:set_action("ch:"..i.." OP3 attack", function(x) o.cc(45,x*4,i) end)
params:add_control("ch:"..i.." OP4 attack",controlspec.new(1,32,'lin',1,16))
params:set_action("ch:"..i.." OP4 attack", function(x) o.cc(46,x*8,i) end)
params:add_control("ch:"..i.." OP1 release",controlspec.new(1,16,'lin',1,8))
params:set_action("ch:"..i.." OP1 release", function(x) o.cc(59,x*8,i) end)
params:add_control("ch:"..i.." OP2 release",controlspec.new(1,16,'lin',1,8))
params:set_action("ch:"..i.." OP2 release", function(x) o.cc(60,x*8,i) end)
params:add_control("ch:"..i.." OP3 release",controlspec.new(1,16,'lin',1,8))
params:set_action("ch:"..i.." OP3 release", function(x) o.cc(61,x*8,i) end)
params:add_control("ch:"..i.." OP4 release",controlspec.new(1,16,'lin',1,8))
params:set_action("ch:"..i.." OP4 release", function(x) o.cc(62,x*8,i) end)
params:add_separator()
end
k:start()
end
function enc(n, delta)
if alt==false then
if n == 1 then
mix:delta("output", delta)
elseif n == 2 then
tracks[chanSelect].accum = (tracks[chanSelect].accum + delta) % tracks[chanSelect].length
tracks[chanSelect].edit = tracks[chanSelect].accum
elseif n == 3 then
tracks[chanSelect].sliders[tracks[chanSelect].edit+1] = tracks[chanSelect].sliders[tracks[chanSelect].edit+1] + delta
if tracks[chanSelect].sliders[tracks[chanSelect].edit+1] > 32 then tracks[chanSelect].sliders[tracks[chanSelect].edit+1] = 32 end
if tracks[chanSelect].sliders[tracks[chanSelect].edit+1] < 0 then tracks[chanSelect].sliders[tracks[chanSelect].edit+1] = 0 end
end
elseif alt==true then
if n == 1 then
if delta > 0 then
if chanSelect <10 then chanSelect = (chanSelect + 1)
else
chanSelect=10
end
end
if delta < 0 then
if chanSelect >1 then chanSelect = (chanSelect - 1)
else
chanSelect=1
end
end
end
if n == 2 then
tracks[chanSelect].sliders[math.random(16)] = math.random(32)
end
if n == 3 then
if delta > 0 then
if tracks[chanSelect].length <16 then tracks[chanSelect].length = (tracks[chanSelect].length + 1)
else
tracks[chanSelect].length=16
end
end
if delta < 0 then
if tracks[chanSelect].length >1 then tracks[chanSelect].length = (tracks[chanSelect].length - 1)
else
tracks[chanSelect].length=1
end
end
end
redraw()
end
end
function key(n, z)
if n==1 and z==1 then
alt=true
end
if n==1 and z==0 then
alt=false
end
if n==2 and z==1 then
if alt == false then
randVal[chanSelect] = 1 - randVal[chanSelect]
if randVal[chanSelect] == 1 then
tracks[chanSelect].random = true
end
if randVal[chanSelect] == 0 then
tracks[chanSelect].random = false
end
end
if alt == true then
for i=1,10 do tracks[i].step = 0 end
end
end
if n==3 and z==1 then
if alt == false then
for i=0,15 do
tracks[chanSelect].sliders[i+1] = 0
end
end
if alt == true then
onVal[chanSelect] = 1 - onVal[chanSelect]
if onVal[chanSelect] == 0 then
tracks[chanSelect].on = false
end
if onVal[chanSelect] == 1 then
tracks[chanSelect].on = true
end
end
end
end
function redraw()
screen.aa(1)
screen.line_width(1.0)
screen.clear()
screen.move(5,10)
screen.text("GENMDM")
screen.move(40,10)
screen.text("ch: "..tracknames[chanSelect])
for i=0, tracks[chanSelect].length-1 do
if i == tracks[chanSelect].edit then
screen.level(15)
else
screen.level(2)
end
screen.move(32+i*4, 48)
screen.line(32+i*4, 46-tracks[chanSelect].sliders[i+1])
screen.stroke()
end
screen.level(10)
screen.move(32+tracks[chanSelect].step*4, 50)
screen.line(32+tracks[chanSelect].step*4, 54)
screen.stroke()
screen.move(15,48)
local val = (tracks[chanSelect].sliders[tracks[chanSelect].edit+1])
--print(val)
screen.text(midinotes[val+1])
--screen.text(midinotes[tracks[chanSelect].sliders[tracks[chanSelect].edit+1]])
screen.move(100,48)
screen.text(1+tracks[chanSelect].edit.."/"..tracks[chanSelect].length)
if tracks[chanSelect].random == true then
screen.move(100,40)
screen.text("rand")
end
if tracks[chanSelect].on == false then
screen.move(100,32)
screen.text("off")
end
screen.update()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment