Here’s a specific task I ran into. Comment, use, enjoy!
local function note_convert(note)
--converts a note string to note value and vice versa
--data
local specials = {
"OFF",
"---"
}
local notestrings = {
"C-",
"C#",
"D-",
"D#",
"E-",
"F-",
"F#",
"G-",
"G#",
"A-",
"A#",
"B-"
}
--subfunctions nstr_to_nval and nval_to_nstr
local function nstr_to_nval(nstr)
--converts a notestring (nstr) into a note value
--catch errors
assert(type(nstr) == "string", "Notestring type must be a string, got ".. type(nstr))
assert(#nstr == 3, "Notestring must be exactly 3 characters long, got ".. #nstr)
local special = table.find(specials, string.sub(nstr,1,3))
local note = table.find(notestrings, string.sub(nstr,1,2))
local octave = tonumber(string.sub(nstr,3))
--catch errors
assert(note or special, "Invalid notestring: " .. ((string.sub(nstr,1,3)) or "nil") .. " , expected format example: C-4")
if note then
assert(type(octave) == "number", "Invalid notestring octave: " .. (string.sub(nstr,3) or "nil") .. " , expected a number (0-9)")
end
--the math
local nval
if note then
nval = note + (octave*12) - 1
else
if nstr == "OFF" then
nval = 120
else
nval = 121 --empty
end
end
return nval
end
--------
local function nval_to_nstr(nval)
--converts a note value (nval) into a notestring
--catch errors
assert(type(nval) == "number", "Note value format must be a number, got" ..type(nval))
assert(nval >= 0 and nval <= 121, "Note value range 0-121, got " ..nval)
--the abc
local nstr
if nval > 119 then
--special
if nval == 120 then
nstr = "OFF"
else
nstr = "---"
end
else
--regular note
local octave = math.floor (nval/12)
local note = nval - (12*octave)
nstr = notestrings[note+1] .. octave
end
return nstr
end
--------
--main
assert(type(note) == "number" or type(note) == "string", "note_conv excpects number or string")
local converted_note
if type(note) == "number" then
converted_note = nval_to_nstr(note)
else
converted_note = nstr_to_nval(note)
end
return converted_note
end
--tests
print(note_convert("C-4")) --result 48
print(note_convert(48)) --result "C-4"
for i = 0,121 do
print(note_convert(note_convert(i))) --translate back&forth, results in sequence from 0-121
end
Edit:slimmed the code down a bit.
Edit:fixed a mistake in notestring octave error catching. And general notestring format error catching.
Edit:took away unused octaves_min and octaves_max. sheesh… got to prune these snips a little better before posting.