This plugin aims to make rhythm game development and music syncing easier than ever before. Import a midi file like you would any other Godot asset, this can then be paired with a "MidiPlayer" node that sends out signals every time a midi event is fired. This project is a work in progress and lacks some features, so feel free to contribute any code or ideas on the pull requests page.
https://github.com/nlaha/godot-midi/assets/10292944/f88acfac-1ff3-49ee-8d25-9ee0ee585d09
https://github.com/nlaha/godot-midi/assets/10292944/543646ec-ed45-406b-a3e5-f2b26caabfbe
This GDExtension addon is compatible with Godot version 4.2.2 and higher. Earlier 4.x versions may work, however they are not officially supported.
Download the latest release from https://github.com/nlaha/godot-midi/releases
If you'd like to download a newer version that hasn't been released, download it from the latest Github Actions run: https://github.com/nlaha/godot-midi/actions/workflows/builds.yml
Copy the godot-midi
folder to your project's addons
folder
Enable the addon in Godot's project settings
Clone the repository with git clone --recursive https://github.com/nlaha/godot-midi.git
Make sure you have SCons installed
Run cd godot-cpp
and scons target=template_debug
or scons target=template_release
to build godot-cpp
Run scons target=template_debug
or scons target=template_release
in the root directory to build the extension
Copy the game/addons/godot_midi
folder to your project's addons folder
Enable the plugin in the Godot project settings menu
NOTE: If you run into import errors or problems with a midi file you downloaded from the internet, it's likely there is a midi event or format that isn't supported by Godot Midi. The best way to fix this is to import the midi file into a DAW (digital audio workstation) or similar software and re-export it. This should convert the midi file into a format easily readable by Godot Midi. I do all my testing with FL Studio so I'd recommend that, you can use the free demo version if you don't have a license.
Connect to the "note" signal in a GDScript
func _ready():
midi_player.note.connect(my_note_callback)
midi_player.play()
func my_note_callback(event, track):
if (event['subtype'] == MIDI_MESSAGE_NOTE_ON): # note on
# do something on note on
elif (event['subtype'] == MIDI_MESSAGE_NOTE_OFF): # note off
# do something on note off
print("[Track: " + str(track) + "] Note played: " + str(event['note']))
Because the game thread frame time can fluctuate depending on the system load, GodotMidi's player is run on a separate thread. Because of this, it's best to use the built-in synchronization feature if you want to sync MIDI events to music.
The good news: it's easy to use! Just call link_audio_stream_player(...)
with your ASP and it will automatically start/stop/pause the ASP for you!
func _ready():
midi_player.loop = true
midi_player.note.connect(my_note_callback)
# link the AudioStreamPlayer in your scene
# that contains the music associated with the midi
# NOTE: this must be an array, you can link multiple ASPs or one as
# shown below and they will all sync with playback of the MIDI
midi_player.link_audio_stream_player([asp])
# this will also start the audio stream player (music)
midi_player.play()
func my_note_callback(event, track):
if (event['subtype'] == MIDI_MESSAGE_NOTE_ON): # note on
# do something on note on
elif (event['subtype'] == MIDI_MESSAGE_NOTE_OFF): # note off
# do something on note off
print("[Track: " + str(track) + "] Note played: " + str(event['note']))
Open the demo project for an included music visualizer script!