Created
May 27, 2023 13:00
-
-
Save Nek/989b7297ed8a5cbf0ea309b581c527b5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- https://github.com/Simon-L/ModScript script for interaction with Akai Fire MIDI controller | |
config.frameDivider = 1 | |
config.bufferSize = 32 | |
done = false | |
buttonTrig = SchmittTrigger.new() | |
OR, XOR, AND = 1, 3, 4 | |
function bitoper(a, b, oper) | |
local r, m, s = 0, 2 ^ 31 | |
repeat | |
s, a, b = a + b + m, a % m, b % m | |
r, m = r + m * oper % (s - a - b), m / 2 | |
until m < 1 | |
return r | |
end | |
function string.fromhex(str) | |
return (str:gsub('..', function(cc) | |
return string.char(tonumber(cc, 16)) | |
end)) | |
end | |
function string.tohex(str) | |
return (str:gsub('.', function(c) | |
return string.format('%02X', string.byte(c)) | |
end)) | |
end | |
function setPadColor(row, col, r, g, b) | |
sendSysex({ | |
0xF0, | |
0x47, 0x7F, 0x43, 0x65, 0, 4, | |
row * 0x10 + col, | |
bitoper(r, 0x7F, AND), | |
bitoper(g, 0x7F, AND), | |
bitoper(b, 0x7F, AND), | |
0xF7 | |
}) | |
-- body | |
end | |
-- row | |
steps = { | |
0, 0, 0, 0, | |
0, 0, 0, 0, | |
0, 0, 0, 0, | |
0, 0, 0, 0, | |
} | |
selectedRow = 1 | |
dirty = true | |
-- Scriabin-Circle | |
COLOURS = { | |
["A"] = 20 * 0, | |
["A#"] = 20 * 1, | |
["B"] = 20 * 2, | |
["C"] = 20 * 3, | |
["C#"] = 20 * 4, | |
["D"] = 20 * 5, | |
["D#"] = 20 * 6, | |
["E"] = 20 * 7, | |
["F"] = 20 * 8, | |
["F#"] = 20 * 9, | |
["G"] = 20 * 10, | |
["G#"] = 20 * 11, | |
} | |
function hsl_to_rgb(h, s, L) | |
h = h/360 | |
local m1, m2 | |
if L<=0.5 then | |
m2 = L*(s+1) | |
else | |
m2 = L+s-L*s | |
end | |
m1 = L*2-m2 | |
local function _h2rgb(m1, m2, h) | |
if h<0 then h = h+1 end | |
if h>1 then h = h-1 end | |
if h*6<1 then | |
return m1+(m2-m1)*h*6 | |
elseif h*2<1 then | |
return m2 | |
elseif h*3<2 then | |
return m1+(m2-m1)*(2/3-h)*6 | |
else | |
return m1 | |
end | |
end | |
return {_h2rgb(m1, m2, h+1/3), _h2rgb(m1, m2, h), _h2rgb(m1, m2, h-1/3)} | |
end | |
-- 20 - 127 | |
-- A0 - G9 | |
function midiToColor(n) | |
-- name_and_octave = MusicUtil.note_num_to_name_struct(n) | |
-- name = name_and_octave[1] | |
-- octave = (name_and_octave[2] + 3) / 11 | |
-- color = hsl_to_rgb(COLOURS[name], 1.0, 0.5) | |
-- display('octave ' .. octave) | |
-- display('name ' .. name) | |
-- display('r ' .. color[1] .. ' g ' .. color[2] .. ' b ' .. color[3]) | |
-- return {color[1]*octave, color[2]*octave, color[3]*octave, } | |
-- display('fract ' .. math.floor(n / (127/11.9) + 1)) | |
-- display('hue ' .. 30 * math.floor(n / (127/11.9) + 1)) | |
h = 30 * math.floor(n / (127/11.9) + 1) | |
-- | |
-- | |
-- 0.3 0.7 | |
-- 0.25 0.5 0.75 1 | |
return hsl_to_rgb(h, 1, 0.5) | |
end | |
function renderUI() | |
for i = 0, 3 do | |
for k = 0, 3 do | |
color = midiToColor(steps[i * 4 + k + 1]) | |
display('color ' .. color[1] .. ' ' .. color[2] .. ' ' .. color[3]) | |
setPadColor(i, k, color[1]*127, color[2]*127, color[3]*127) | |
end | |
end | |
if selectedRow == 1 then | |
sendMidiMessage(0xb, 36, 127) | |
else | |
sendMidiMessage(0xb, 36, 0) | |
end | |
if selectedRow == 2 then | |
sendMidiMessage(0xb, 37, 127) | |
else | |
sendMidiMessage(0xb, 37, 0) | |
end | |
if selectedRow == 3 then | |
sendMidiMessage(0xb, 38, 127) | |
else | |
sendMidiMessage(0xb, 38, 0) | |
end | |
if selectedRow == 4 then | |
sendMidiMessage(0xb, 39, 127) | |
else | |
sendMidiMessage(0xb, 39, 0) | |
end | |
end | |
-- 128 notes 0 - 127 | |
-- 12 colors | |
-- 120 notes 7 - 127 | |
-- 360 / 120 | |
-- 96 colors | |
-- 21 -- 116 | |
-- 1 -- 96 | |
function process(block) | |
for i = 1, block.midiInputSize do | |
msg = Message(block.midiInput[i]) | |
-- display('type ' .. | |
-- string.format("0x%x", msg.type) .. ' channel ' .. msg.channel .. ' note ' .. msg.note .. ' value ' .. msg.value) | |
if msg.type == NOTE_ON then | |
if (msg.note >= 36 and msg.note <= 39) then | |
selectedRow = msg.note - 35 | |
renderUI() | |
end | |
elseif msg.type == CC then | |
if (msg.note >= 16 and msg.note <= 19) then | |
delta = msg.value | |
display('delta ' .. delta) | |
if delta > 64 then | |
delta = delta - 128 | |
end | |
val = steps[(selectedRow - 1) * 4 + msg.note - 15] | |
val = val + delta | |
if val < 0 then val = 0 end | |
if val > 127 then val = 127 end | |
steps[(selectedRow - 1) * 4 + msg.note - 15] = val | |
renderUI() | |
end | |
end | |
end | |
end | |
-- if buttonTrig:process(block.button and 0 or 1) then | |
-- for i = 0, 255 do | |
-- sendMidiMessage(0xb, i, 0) | |
-- sendMidiMessage(NOTE_OFF, 36, 127) | |
-- end | |
-- if dirty then | |
-- renderUI() | |
-- dirty = false | |
-- end | |
-- setPadColor(0, 0, 0, 0, 0) | |
-- sendSysex({ 0xF0, 0x47, 0x7F, 0x43, 0x65, 0x00, 0x01, 0x00, 0xFF, 0x00, 0x00, 0xF7 }) | |
-- end | |
-- end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment