About
After realizing most solutions to this is to either port a pure lua midi parser to roblox or use a incredibly old script, which is often tedious and mostly a pain in the bum. So I decided to make one myself, for anyone to use, this midi parser turns raw data from Http service to a table that shouldnt be hard to read.
Some Important notes
there are some or a lot of status bytes and meta events i have not implemented yet (laziness!!), but if you need to it shouldnt be that hard.
to do so add a module under the StatusBytes folder in which it should be named after the Hex or decimal of the status byte you want to add in the module it should include this template
return function(self)
local Byte = self:ReadBytes(1) --or self:ReadBytes()
local RawText = self:ReadRaw(Step) --or nil = 1 step
end
I am aware that richie0866 has already made one that looks better but his code is pretty chunky.
Lastly, as the title said there is no midi player included
Example code
local Data = Http:GetAsync(URL)
local ParseMidi = require(...)
local Midi = ParseMidi.new(Data)
local Result: ParseMidi.Result = Midi:Start()
Result.RawStack --all the messages and meta events ordered by when they show up
Result.Tracks[1] -- chunk 1 with all the meta events and messages
local function visualizeNotes(TrackData)
local Delta = 0
for _, EventData in ipairs(TrackData) do
local IsNoteOn = EventData.Name == "NoteOn"
if IsNoteOn then
local NoteNumber = EventData.Data.NoteNumber
local NoteVelocity = EventData.NoteVelocity
local DeltaTimeInTicks = EventData.DeltaTime
local Seconds = (DeltaTimeInTicks / Result.Division) * (60 / 90) --tempo is 90 derrived from 60000000 / 666666
local Part = Instance.new("Part")
Part.Size = Vector3.new(Seconds * 10, 1, 1) --regularly it would be too small
Part.Anchored = true
Part.Position = Vector3.new(Delta + (Part.Size.X / 2), NoteNumber, 0)
Part.Parent = workspace
Delta += Seconds * 10
end
end
end
visualizeNotes(Result.Tracks[1])
LuaMidi from luarocks is a pure lua midi parser I think you should look at and try to compare with it (performance, etc). You can use midi2score() function and just plug in the returned value of HttpService:GetAsync(mid file link). I have my own midi player that utlizes that module.
Will do, also upon benchmarking on a 100kb file the pure lua one is indeed faster by around 7 times, but i would say theyre both negligible as the time is within the milisecond range 1ms and 7ms, although the pure lua one is faster by a lot, it isnt in readability . One major bottleneck i think is opting to use lua’s string.unpack rather than some bit manipulation (maybe in the future).
Look up the MIDI channels, it should provide you a basic outline of which channels are your tuned percussion, untuned percussion, synth etc. Channel 9 is usually the percussion.
According to this MIDI Program Change message | RecordingBlogs percussion is on channel 9 (according to a comment this often differs from how you count, from zero or one). I have seen your Instruments file but since im no audio engineer idk how to use it or something. Btw whats the formula to get Pitch? Also I have found this neat website with all the assets Samples by MIDI Instrument.
When I find the motivation ill rework the entire think, hopefully it wouldnt be that messy.