Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
199 lines (168 sloc) 4.08 KB
--
-- ////\\\\
-- ////\\\\ LINN
-- ////\\\\ BY NEAUOIRE
-- \\\\////
-- \\\\//// LINN LAYOUT
-- \\\\////
--
local g
local viewport = { width = 128, height = 64, frame = 0 }
local focus = { x = 1, y = 1, brightness = 15 }
local chan = 1
local keys_down = 0
local midi_signal_out
local keys = { 'C','C#','D','D#','E','F','F#','G','G#','A','A#','B' }
local notes = {
'F3', 'F3#', 'G3', 'G3#', 'A3', 'A3#', 'B3', 'C4', 'C4#', 'D4', 'D4#', 'E4', 'F4', 'F4#', 'G4', 'G4#',
'C3', 'C3#', 'D3', 'D3#', 'E3', 'F3', 'F3#', 'G3', 'G3#', 'A3', 'A3#', 'B3', 'C4', 'C4#', 'D4', 'D4#',
'G2', 'G2#', 'A2', 'A2#', 'B2', 'C3', 'C3#', 'D3', 'D3#', 'E3', 'F3', 'F3#', 'G3', 'G3#', 'A3', 'A3#',
'D2', 'D2#', 'E2', 'F2', 'F2#', 'G2', 'G2#', 'A2', 'A2#', 'B2', 'C3', 'C3#', 'D3', 'D3#', 'E3', 'F3',
'A1', 'A1#', 'B1', 'C3', 'C2#', 'D2', 'D2#', 'E2', 'F2', 'F2#', 'G2', 'G2#', 'A2', 'A2#', 'B2', 'C3',
'E1', 'F1', 'F1#', 'G1', 'G1#', 'A1', 'A1#', 'B1', 'C2', 'C2#', 'D2', 'D2#', 'E2', 'F2', 'F2#', 'G2',
'B0', 'C1', 'C1#', 'D1', 'D1#', 'E1', 'F1', 'F1#', 'G1', 'G1#', 'A1', 'A1#', 'B1', 'C2', 'C2#', 'D2',
'F0#', 'G0', 'G0#', 'A0', 'A0#', 'B0', 'C1', 'C1#', 'D1', 'D1#', 'E1', 'F1', 'F1#', 'G1', 'G1#', 'A1',
}
local index_of = function(list,value)
for i=1,#list do
if list[i] == value then return i end
end
return -1
end
-- Main
function init()
connect()
-- Render Style
screen.level(15)
screen.aa(0)
screen.line_width(1)
-- Render
update()
end
function connect()
g = grid.connect()
g.key = on_grid_key
midi_signal_out = midi.connect(1)
end
function is_connected()
return g.device ~= nil
end
function note_at(i)
local n = notes[i]
local k = n:sub(1, 1)
local o = tonumber(n:sub(2, 2))
local s = n:match('#')
local p = n:gsub(o,'')
local v = index_of(keys,p) + (12 * (o+2)) - 1
local l = 0
if p == 'C' then
l = 15
elseif s then
l = 0
else
l = 5
end
return { i = i, k = k, o = o, s = s, v = v, l = l, p = p }
end
function pos_at(id)
return { x = ((id-1) % 16) + 1, y = math.floor(id / 16) + 1 }
end
function id_at(x,y)
return ((y-1) * 16) + x
end
function on_grid_key(x,y,z)
if z == 1 then
on_grid_key_down(x,y)
else
on_grid_key_up(x,y)
end
update()
end
function on_grid_key_down(x,y)
focus.x = x
focus.y = y
midi_signal_out:note_on(note_at(id_at(x,y)).v,127)
keys_down = keys_down + 1
end
function on_grid_key_up(x,y)
midi_signal_out:note_off(note_at(id_at(x,y)).v,127)
keys_down = keys_down - 1
end
function update()
g:all(0)
for i=1,128 do
pos = pos_at(i)
note = note_at(i)
g:led(pos.x,pos.y,note.l)
end
g:led(focus.x,focus.y,10)
g:refresh()
redraw()
end
-- Interactions
function key(id,state)
if id == 2 and state == 1 then
focus.brightness = 15
elseif id == 3 and state == 1 then
focus.brightness = 5
end
update()
end
function enc(id,delta)
if id == 2 then
focus.x = clamp(focus.x + delta, 1, 16)
elseif id == 3 then
focus.y = clamp(focus.y + delta, 1, 8)
end
update()
end
-- Render
function draw_pixel(x,y)
if focus.x == x and focus.y == y then
screen.fill()
screen.level(15)
end
screen.pixel((x*offset.spacing) + offset.x, (y*offset.spacing) + offset.y)
if focus.x == x and focus.y == y then
screen.fill()
screen.level(1)
end
end
function draw_grid()
if is_connected() ~= true then return end
screen.level(1)
offset = { x = 30, y = 13, spacing = 4 }
for x=1,16,1 do
for y=1,8,1 do
draw_pixel(x,y)
end
end
screen.fill()
end
function draw_label()
if keys_down < 1 then return end
note = note_at(id_at(focus.x,focus.y))
screen.level(15)
local line_height = 8
screen.move(34,56)
screen.text(note.p..''..note.o..' '..note.v)
screen.move(94,56)
screen.text_right('CHAN'..chan)
screen.stroke()
end
function redraw()
screen.clear()
if is_connected() ~= true then
screen.move(5,10)
screen.text('Grid is not connected.')
screen.fill()
else
draw_grid()
draw_label()
end
screen.update()
end
-- Utils
function clamp(val,min,max)
return val < min and min or val > max and max or val
end
You can’t perform that action at this time.