2021-06-06 18:34:44 +06:00

103 lines
2.3 KiB
Plaintext

-- @include constants.txt
-- @include track.txt
-- @include /koptilnya/libs/utils.txt
require("track.txt")
require("/koptilnya/libs/utils.txt")
local CONSTANTS = require("constants.txt")
function byteToHex(byte)
return tostring(byte)
end
MidiPlayer = class("MidiPlayer")
function MidiPlayer:initialize()
self._startTime = 0
self._buffer = nil
self._midiChunksByteLength = nil
self._division = 0
self._format = nil
self._setIntervalId = false
self._tracks = {}
self._instruments = {}
self._defaultTempo = 120
self._tempo = null
self._startTick = 0
self._tick = 0
self._lastTick = null
self._inLoop = false
self._totalTicks = 0
self._events = {}
self._totalEvents = 0
self._eventListeners = {}
end
function MidiPlayer:loadURL(link)
if not http.canRequest() then
return
end
http.get(link, function(data, len)
self._buffer = data
self:_fileLoaded()
end)
end
function MidiPlayer:_fileLoaded()
if not self:isValid() then
throw("Invalid MIDI file; should start with MThd")
end
self:setTempo(self._defaultTempo)
self:_parseDivision()
self:_parseFormat()
self:_parseTracks()
end
function MidiPlayer:isValid()
return string.char(unpack(byteTable(self._buffer, 1, 4))) == "MThd"
end
function MidiPlayer:setTempo(tempo)
self._tempo = tempo
end
function MidiPlayer:_parseDivision()
self._division = tonumber(bytesToHex(byteTable(self._buffer, 13, 2)))
end
function MidiPlayer:_parseFormat()
self._format = tonumber(bytesToHex(byteTable(self._buffer, 9, 2)))
end
function MidiPlayer:_parseTracks()
self._tracks = {}
local offset = 1
while offset < #self._buffer do
local length = tonumber(bytesToHex(byteTable(self._buffer, offset + 4, 4)))
if string.char(unpack(byteTable(self._buffer, offset, 4))) == "MTrk" then
table.insert(self._tracks, MidiTrack:new(#self._tracks + 1, string.sub(self._buffer, offset + 8, offset + 8 + length)))
end
offset = offset + length + 8
end
end
function MidiPlayer:resetTracks()
for _, v in pairs(self._tracks) do
v:reset()
end
end
function MidiPlayer:enableTrack(id)
self._tracks[id]:enable()
end
function MidiPlayer:disableTrack(id)
self._tracks[id]:disable()
end