Created note API

Functionality:
* `note.midi(n: number or string)`: Converts a note in string form (e.g. A#4 or Gb3, will be documented on the wiki) or a given frequency into the respective MIDI code
* `note.freq(n: number or string)`: Converts a note in string form (e.g. A#4) or a given MIDI code into the respective frequency
* `note.get(n: number)`: Converts a MIDI value back into a string; if you have a frequency to convert, just use note.get(note.midi(frequency))
* `note.ticks(n: number)`: Converts note block ticks (0-24) into MIDI code (34-58, respectively) and vice-versa. Useful for use with note blocks and OpenComponents
* `note.play(tone: string or number,duration: number)`: Plays a note from a string or MIDI code via computer.beep
This commit is contained in:
Vexatos 2014-04-30 17:28:15 +02:00
parent bb7dd9e966
commit 20c1c1ac0a

View File

@ -0,0 +1,120 @@
--Provides all music notes in range of computer.beep in MIDI and frequency form
--Author: Vexatos
local computer = require("computer")
local note = {}
local notes = {}
local reverseNotes = {}
do
local tempNotes = {
"c",
"c#",
"d",
"d#",
"e",
"f",
"f#",
"g",
"g#",
"a",
"a#",
"b"
}
local sNotes = {}
local bNotes = {}
--Registers all possible notes in order
do
table.insert(sNotes,"a0")
table.insert(sNotes,"a#0")
table.insert(bNotes,"bb0")
table.insert(sNotes,"b0")
for i = 1,6 do
for _,v in ipairs(tempNotes) do
table.insert(sNotes,v..tostring(i))
if #v == 1 and v ~= "c" and v ~= "f" then
table.insert(bNotes,v.."b"..tostring(i))
end
end
end
end
for i=21,95 do
notes[sNotes[i-20]]=tostring(i)
end
do
for k,v in pairs(notes) do
reverseNotes[tonumber(v)]=k
end
end
--This is registered after reverseNotes to avoid conflicts
for k,v in ipairs(bNotes) do
notes[v]=tostring(notes[string.gsub(v,"(.)b(.)","%1%2")]-1)
end
end
--Converts string or frequency into MIDI code
function note.midi(n)
if type(n) == "string" then
n = string.lower(n)
if tonumber(notes[n])~=nil then
return tonumber(notes[n])
else
error("Error: Wrong input "..tostring(n).." given to note.midi, needs to be <note>[semitone sign]<octave>, e.g. A#0 or Gb4")
end
elseif type(n) == "number" then
return math.floor((12*math.log(n/440,2))+69)
else
error("Error: Wrong input "..tostring(n).." given to note.midi, needs to be a number or a string")
end
end
--Converts String or MIDI code into frequency
function note.freq(n)
if type(n) == "string" then
n = string.lower(n)
if tonumber(notes[n])~=nil then
return math.pow(2,(tonumber(notes[n])-69)/12)*440
else
error("Error: Wrong input "..tostring(n).." given to note.freq, needs to be <note>[semitone sign]<octave>, e.g. A#0 or Gb4",2)
end
elseif type(n) == "number" then
return math.pow(2,(n-69)/12)*440
else
error("Error: Wrong input "..tostring(n).." given to note.freq, needs to be a number or a string",2)
end
end
--Converts a MIDI value back into a string
function note.get(n)
n = tonumber(n)
if reverseNotes[n] then
return string.upper(string.match(reverseNotes[n],"^(.)"))..string.gsub(reverseNotes[n],"^.(.*)","%1")
else
error("Error: Attempt to get a note for a non-exsisting MIDI code",2)
end
end
--Converts Note block ticks (0-24) to MIDI code (34-58) and vice-versa
function note.ticks(n)
if type(n) == "number" then
if n>=0 and n<=24 then
return n+34
elseif n>=34 and n<=58 then
return n-34
else
error("Error: Wrong input "..tostring(n).." given to note.ticks, needs to be a number [0-24 or 34-58]",2)
end
else
error("Error: Wrong input "..tostring(n).." given to note.ticks, needs to be a number",2)
end
end
--Plays a tone, input is either the note as a string or the MIDI code as well as the duration of the tone
function note.play(tone,duration)
computer.beep(note.freq(tone),duration)
end
return note