Skip to content

Instantly share code, notes, and snippets.

@carltesta

carltesta/genmdm.lua

Last active Sep 1, 2018
Embed
What would you like to do?
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
You can’t perform that action at this time.