I recently started working on a virtual piano keyboard game, with the goal being to test out some of the modern Roblox audio API features and create something with more features than most other piano games on the platform. I’ve previously created things similar to this (not released) and one of the most important features that this version makes use of is the ability to use a custom loop region. This makes it possible to support much more complex samples and instruments.
Anyways, now that it’s in a decent state (and I’ve finally been promoted from visitor to member on the DevForums) I thought I’d showcase it here.
I imported all the samples from the default soundfont that comes with Windows (C:\Windows\System32\drivers\gm.dls)
The game is currently available here, but to better demonstrate the capabilities of the engine, I recorded some examples where I imported and played various MIDI files:
DevForum file size limit being 10 mb meant I had to compress some of these
Would I be able to play directly using a midi app on this, or no? and would I be able to play with QWERTY? I am used to playing virtual piano with QWERTY (or just computer keyboards in general), or is it primarily just a midi file player? would be cool to have something to mess around on that isnt just visual pianos after so many years now..
It primarily supports keyboard usage at the moment, however I am looking into potential ways to connect MIDI devices to the roblox client. As for playing MIDI files, I have the code to do so but have not yet exposed it in the UI.
The macro approach makes sense for a workaround. How is the latency looking when sending messages through Python? Real-time performance needs to be pretty tight or it’ll feel off.
As far as latency goes, I estimate around 300-500ms between hearing my keyboard play the note and hearing the game play the note. Part of this is likely due to having to send many keystrokes at once in order to send data (one note on event looks like this: 905231g) which is especially noticeable when smashing the keyboard or playing multi instrument songs, which can cause the game to stutter when multiple events happen at once..
Though, I just checked the game logs, and… There might be some latency issues when it comes to my games input handler as well.
300-500ms is way too high for a piano engine. If you’re seeing stuttering during chords, the input handler or the macro itself is definitely bottlenecking. You should check if the Python script is batching too much data or if the Roblox side is struggling to parse those strings quickly enough.
After recording my game and macro output, there appears to be about 4 frames (67 ms) between the key being logged by python and the key showing up in roblox.
Also, I actually measured the latency (by recording both the piano output and roblox output, and taking the distance between the two sounds starting) and its appears to be 286 ms
I also benchmarked the python script, and it takes 5 ms to press all the keys for one midi event.
67ms of delay between Python logging and Roblox receiving it is still a massive gap for something that needs to be instant. If the macro is just simulating keystrokes, you’re likely hitting Windows input buffer delays or Roblox’s own input processing overhead. You should check if there’s any heavy logic running in your game’s input listener that might be stalling the main thread when those events arrive.
286ms is still massive for a musical instrument. If Python is only taking 5ms, then the bottleneck is likely in how the Roblox client is receiving or processing those network packets/input events. You should look into whether the engine’s internal audio playback or the task scheduler is introducing that delay.
My game seems to be reporting 1-2ms from the moment the first keystroke is processed to the moment :Play() is called… I have a feeling this is a Roblox limitation and/or delay between the OS MIDI interface and the python script.
If your internal game logic is only showing 1-2ms, then the delay is definitely happening before it even hits the engine. You’re likely looking at OS-level MIDI processing or the Python script’s interaction with the Windows input buffer. It’s hard to bypass that without a more direct way to pipe data into Roblox than simulated keystrokes.