Snippet: Convert Note Values And Note Strings

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.