Skip to content

G0retZ/godot-midi-mport

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

spent several days working on this and debugging. Inintially I tryed to use GDScript Midi File Parser but it turned out confusing and not very convenient to use. So I decided to improve it... And now we are here 🙃

Godot 4+ Importer for MIDI (.mid) files.

This addon allows you to import and parse MIDI files in your project as any other resource. It handles almost all available MIDI files features and also has some encapsulated tools for easier use.

Some features:

  • Importing MIDI files of all currently available formats (0-2): Single track, polyphony multitrack and multi-sequence.
  • Supports both SMPTE fps and PPQ timnig parsing and calculations.
  • Has built-in tempo-map extraction for any Track.
  • Has encapsulated SMPTE offset calculation in seconds.
  • The MidiData class itself is thoroghly documented and helps to additionally understand the MIDI format behaviour.

Installation:

  1. Add to the addons folder like any other regular plugin.
  2. Enable it in the project settings as usually.

Usage:

Import MIDI file by drag-n-drop as you do with pictures and other resources. Now you can use in a same way as any other resource: drag-n-drop to Nodes, load, preload etc.

Simple example (just plays some sounds from the first track):

var midi_data: MidiData = load("res://samples/smoke-on-the-water.mid")

func _play():
	var inital_delay := midi_data.tracks[0].get_offset_in_seconds()
	match midi_data.header.format:
		MidiData.Header.Format.SINGLE_TRACK, MidiData.Header.Format.MULTI_SONG:
			var us_per_beat: int = 500_000
			for event in midi_data.tracks[0].events:
				inital_delay += midi_data.header.convert_to_seconds(us_per_beat, event.delta_time)
				var tempo := event as MidiData.Tempo
				var note_on := event as MidiData.NoteOn
				if tempo != null:
					us_per_beat = tempo.us_per_beat
				elif note_on != null:
					# TODO: wait for inital_delay and play note_on.note
					inital_delay = 0
		MidiData.Header.Format.MULTI_TRACK:
			var index = 0
			var tempo_map: Array[Vector2i] = midi_data.tracks[0].get_tempo_map()
			var us_per_beat := tempo_map[index].y
			var time: int = 0
			for event in midi_data.tracks[1].events:
				time += event.delta_time
				while time >= tempo_map[index].x:
					index += 1
					us_per_beat = tempo_map[index].y
				inital_delay += midi_data.header.convert_to_seconds(us_per_beat, event.delta_time)
				var note_on := event as MidiData.NoteOn
				if note_on != null:
					# TODO: wait for inital_delay and play note_on.note
					inital_delay = 0

MIDI Specification resources used:

Enjoy using it!

🌻 If you find this addon helpful, please consider supporting my efforts by buying me a coffee (donating)! I would appreciate it very much 😊

About

Godot MIDI files importer

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published