mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-17 11:15:12 -04:00
Merge pull request #243 from Vexatos/patch-4
Created `note` API to allow note name based use of `computer.beep()`.
This commit is contained in:
commit
366fb98b10
126
src/main/resources/assets/opencomputers/lua/rom/lib/note.lua
Normal file
126
src/main/resources/assets/opencomputers/lua/rom/lib/note.lua
Normal file
@ -0,0 +1,126 @@
|
||||
--Provides all music notes in range of computer.beep in MIDI and frequency form
|
||||
--Author: Vexatos
|
||||
local computer = require("computer")
|
||||
|
||||
local note = {}
|
||||
--The table that maps note names to their respective MIDI codes
|
||||
local notes = {}
|
||||
--The reversed table "notes"
|
||||
local reverseNotes = {}
|
||||
|
||||
do
|
||||
--All the base notes
|
||||
local tempNotes = {
|
||||
"c",
|
||||
"c#",
|
||||
"d",
|
||||
"d#",
|
||||
"e",
|
||||
"f",
|
||||
"f#",
|
||||
"g",
|
||||
"g#",
|
||||
"a",
|
||||
"a#",
|
||||
"b"
|
||||
}
|
||||
--The table containing all the standard notes and # semitones in correct order, temporarily
|
||||
local sNotes = {}
|
||||
--The table containing all the b semitones
|
||||
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
|
||||
|
||||
--Reversing the whole table in reverseNotes, used for note.get
|
||||
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("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("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("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("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.name(n)
|
||||
n = tonumber(n)
|
||||
if reverseNotes[n] then
|
||||
return string.upper(string.match(reverseNotes[n],"^(.)"))..string.gsub(reverseNotes[n],"^.(.*)","%1")
|
||||
else
|
||||
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("Wrong input "..tostring(n).." given to note.ticks, needs to be a number [0-24 or 34-58]",2)
|
||||
end
|
||||
else
|
||||
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
|
Loading…
x
Reference in New Issue
Block a user