Midi2lua Today
midi2lua does not magically create sound. It gives you events. You still need a soundfont or a synthesizer (like Soloud, FMOD, or Roblox’s Sound objects) to turn those note pitches into audio. Think of it as the sheet music, not the orchestra.
Because writing a raw binary MIDI parser in Lua from scratch can be complex, the most "helpful" workflow for many developers is a two-step process:
However, if you want a pure Lua solution for simple Type 0 MIDI files (single track), here is a lightweight parser snippet.
Even with a great tool, midi2lua conversions can fail silently. Here is what to watch for.
When creating custom charts for rhythm games that use Lua (such as modded versions of Friday Night Funkin’ using Psych Engine), you need to convert chart files (.mid or .json) into game-readable scripts. midi2lua allows modders to compose complex rhythms in FL Studio or Reaper, then instantly convert those note timings into Lua tables that the game engine polls every frame.
Using a standard CLI tool (assuming midi2lua.py):
python midi2lua.py my_song.mid -o my_song.lua
Flags to look for:
Overview
Why convert MIDI to Lua
Core concepts
Typical Lua event structure
Parsing MIDI — methodical steps
Tick → second conversion (algorithm)
Design choices to consider
Example: Minimal parser outline (pseudocode) midi2lua
Example Lua output (small excerpt)
-- midi2lua output: events in seconds
events =
t = 0.000, type = "note", ch = 1, note = 60, vel = 100, dur = 0.5 ,
t = 0.500, type = "note", ch = 1, note = 64, vel = 110, dur = 0.5 ,
t = 1.000, type = "cc", ch = 1, cc = 1, val = 64 ,
-- simple player: advance time and trigger events
function play(clock_time, synth)
-- synth must implement note_on(ch,note,vel) and note_off(...)
for _, e in ipairs(events) do
if not e.played and clock_time >= e.t then
if e.type == "note" then
synth:note_on(e.ch, e.note, e.vel)
-- schedule note_off at e.t + e.dur (engine-dependent)
elseif e.type == "cc" then
synth:cc(e.ch, e.cc, e.val)
end
e.played = true
end
end
end
Practical example: tempo changes and conversion
Optimizations
Toolchains and libraries (recommended approach)
Sample conversion workflow (practical)
Debugging tips
Use cases
Further extensions
If you want, I can:
A single Lua file that returns a table like:
-- Generated by midi2lua
return
format = 1,
ticks_per_beat = 480,
tracks =
-- Track 0: Piano
events =
tick = 0, type = "note_on", channel = 0, note = 60, velocity = 100 ,
tick = 120, type = "note_off", channel = 0, note = 60, velocity = 64 ,
tick = 240, type = "tempo", bpm = 120 ,
-- etc.
Optionally, the converter can:
midi2lua is a utility (or script) that parses a standard MIDI file (.mid) and outputs a Lua table representation of its musical data. This allows developers to embed procedural music playback, note-accurate event triggering, or rhythm-based game logic directly into Lua environments (e.g., LÖVE2D, Roblox, Defold, PICO-8, or custom embedded systems).
The output is self-contained Lua code – no external MIDI parser or real-time MIDI playback required at runtime.