Browse Source

Document InputEventMIDI and add some missing 0xF MIDI messages

Aaron Franke 3 years ago
parent
commit
de9adcf045
4 changed files with 131 additions and 7 deletions
  1. 11 0
      core/core_constants.cpp
  2. 11 0
      core/input/input_enums.h
  3. 40 7
      doc/classes/@GlobalScope.xml
  4. 69 0
      doc/classes/InputEventMIDI.xml

+ 11 - 0
core/core_constants.cpp

@@ -476,6 +476,17 @@ void register_global_constants() {
 	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PROGRAM_CHANGE);
 	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PROGRAM_CHANGE);
 	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CHANNEL_PRESSURE);
 	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CHANNEL_PRESSURE);
 	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PITCH_BEND);
 	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PITCH_BEND);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SYSTEM_EXCLUSIVE);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, QUARTER_FRAME);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SONG_POSITION_POINTER);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SONG_SELECT);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, TUNE_REQUEST);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, TIMING_CLOCK);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, START);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CONTINUE);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, STOP);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, ACTIVE_SENSING);
+	BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SYSTEM_RESET);
 
 
 	// error list
 	// error list
 
 

+ 11 - 0
core/input/input_enums.h

@@ -95,6 +95,17 @@ enum class MIDIMessage {
 	PROGRAM_CHANGE = 0xC,
 	PROGRAM_CHANGE = 0xC,
 	CHANNEL_PRESSURE = 0xD,
 	CHANNEL_PRESSURE = 0xD,
 	PITCH_BEND = 0xE,
 	PITCH_BEND = 0xE,
+	SYSTEM_EXCLUSIVE = 0xF0,
+	QUARTER_FRAME = 0xF1,
+	SONG_POSITION_POINTER = 0xF2,
+	SONG_SELECT = 0xF3,
+	TUNE_REQUEST = 0xF6,
+	TIMING_CLOCK = 0xF8,
+	START = 0xFA,
+	CONTINUE = 0xFB,
+	STOP = 0xFC,
+	ACTIVE_SENSING = 0xFE,
+	SYSTEM_RESET = 0xFF,
 };
 };
 
 
 enum class MouseButton {
 enum class MouseButton {

+ 40 - 7
doc/classes/@GlobalScope.xml

@@ -2165,25 +2165,58 @@
 			The maximum number of game controller axes: OpenVR supports up to 5 Joysticks making a total of 10 axes.
 			The maximum number of game controller axes: OpenVR supports up to 5 Joysticks making a total of 10 axes.
 		</constant>
 		</constant>
 		<constant name="MIDI_MESSAGE_NOTE_OFF" value="8" enum="MIDIMessage">
 		<constant name="MIDI_MESSAGE_NOTE_OFF" value="8" enum="MIDIMessage">
-			MIDI note OFF message.
+			MIDI note OFF message. See the documentation of [InputEventMIDI] for information of how to use MIDI inputs.
 		</constant>
 		</constant>
 		<constant name="MIDI_MESSAGE_NOTE_ON" value="9" enum="MIDIMessage">
 		<constant name="MIDI_MESSAGE_NOTE_ON" value="9" enum="MIDIMessage">
-			MIDI note ON message.
+			MIDI note ON message. See the documentation of [InputEventMIDI] for information of how to use MIDI inputs.
 		</constant>
 		</constant>
 		<constant name="MIDI_MESSAGE_AFTERTOUCH" value="10" enum="MIDIMessage">
 		<constant name="MIDI_MESSAGE_AFTERTOUCH" value="10" enum="MIDIMessage">
-			MIDI aftertouch message.
+			MIDI aftertouch message. This message is most often sent by pressing down on the key after it "bottoms out".
 		</constant>
 		</constant>
 		<constant name="MIDI_MESSAGE_CONTROL_CHANGE" value="11" enum="MIDIMessage">
 		<constant name="MIDI_MESSAGE_CONTROL_CHANGE" value="11" enum="MIDIMessage">
-			MIDI control change message.
+			MIDI control change message. This message is sent when a controller value changes. Controllers include devices such as pedals and levers.
 		</constant>
 		</constant>
 		<constant name="MIDI_MESSAGE_PROGRAM_CHANGE" value="12" enum="MIDIMessage">
 		<constant name="MIDI_MESSAGE_PROGRAM_CHANGE" value="12" enum="MIDIMessage">
-			MIDI program change message.
+			MIDI program change message. This message sent when the program patch number changes.
 		</constant>
 		</constant>
 		<constant name="MIDI_MESSAGE_CHANNEL_PRESSURE" value="13" enum="MIDIMessage">
 		<constant name="MIDI_MESSAGE_CHANNEL_PRESSURE" value="13" enum="MIDIMessage">
-			MIDI channel pressure message.
+			MIDI channel pressure message. This message is most often sent by pressing down on the key after it "bottoms out". This message is different from polyphonic after-touch as it indicates the highest pressure across all keys.
 		</constant>
 		</constant>
 		<constant name="MIDI_MESSAGE_PITCH_BEND" value="14" enum="MIDIMessage">
 		<constant name="MIDI_MESSAGE_PITCH_BEND" value="14" enum="MIDIMessage">
-			MIDI pitch bend message.
+			MIDI pitch bend message. This message is sent to indicate a change in the pitch bender (wheel or lever, typically).
+		</constant>
+		<constant name="MIDI_MESSAGE_SYSTEM_EXCLUSIVE" value="240" enum="MIDIMessage">
+			MIDI system exclusive message. This has behavior exclusive to the device you're receiving input from. Getting this data is not implemented in Godot.
+		</constant>
+		<constant name="MIDI_MESSAGE_QUARTER_FRAME" value="241" enum="MIDIMessage">
+			MIDI quarter frame message. Contains timing information that is used to synchronize MIDI devices. Getting this data is not implemented in Godot.
+		</constant>
+		<constant name="MIDI_MESSAGE_SONG_POSITION_POINTER" value="242" enum="MIDIMessage">
+			MIDI song position pointer message. Gives the number of 16th notes since the start of the song. Getting this data is not implemented in Godot.
+		</constant>
+		<constant name="MIDI_MESSAGE_SONG_SELECT" value="243" enum="MIDIMessage">
+			MIDI song select message. Specifies which sequence or song is to be played. Getting this data is not implemented in Godot.
+		</constant>
+		<constant name="MIDI_MESSAGE_TUNE_REQUEST" value="246" enum="MIDIMessage">
+			MIDI tune request message. Upon receiving a tune request, all analog synthesizers should tune their oscillators.
+		</constant>
+		<constant name="MIDI_MESSAGE_TIMING_CLOCK" value="248" enum="MIDIMessage">
+			MIDI timing clock message. Sent 24 times per quarter note when synchronization is required.
+		</constant>
+		<constant name="MIDI_MESSAGE_START" value="250" enum="MIDIMessage">
+			MIDI start message. Start the current sequence playing. This message will be followed with Timing Clocks.
+		</constant>
+		<constant name="MIDI_MESSAGE_CONTINUE" value="251" enum="MIDIMessage">
+			MIDI continue message. Continue at the point the sequence was stopped.
+		</constant>
+		<constant name="MIDI_MESSAGE_STOP" value="252" enum="MIDIMessage">
+			MIDI stop message. Stop the current sequence.
+		</constant>
+		<constant name="MIDI_MESSAGE_ACTIVE_SENSING" value="254" enum="MIDIMessage">
+			MIDI active sensing message. This message is intended to be sent repeatedly to tell the receiver that a connection is alive.
+		</constant>
+		<constant name="MIDI_MESSAGE_SYSTEM_RESET" value="255" enum="MIDIMessage">
+			MIDI system reset message. Reset all receivers in the system to power-up status. It should not be sent on power-up itself.
 		</constant>
 		</constant>
 		<constant name="OK" value="0" enum="Error">
 		<constant name="OK" value="0" enum="Error">
 			Methods that return [enum Error] return [constant OK] when no error occurred. Note that many functions don't return an error code but will print error messages to standard output.
 			Methods that return [enum Error] return [constant OK] when no error occurred. Note that many functions don't return an error code but will print error messages to standard output.

+ 69 - 0
doc/classes/InputEventMIDI.xml

@@ -1,27 +1,96 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="InputEventMIDI" inherits="InputEvent" version="4.0">
 <class name="InputEventMIDI" inherits="InputEvent" version="4.0">
 	<brief_description>
 	<brief_description>
+		Input event for MIDI inputs.
 	</brief_description>
 	</brief_description>
 	<description>
 	<description>
+		InputEventMIDI allows receiving input events from MIDI devices such as a piano. MIDI stands for Musical Instrument Digital Interface.
+		MIDI signals can be sent over a 5-pin MIDI connector or over USB, if your device supports both be sure to check the settings in the device to see which output it's using.
+		To receive input events from MIDI devices, you need to call [method OS.open_midi_inputs]. You can check which devices are detected using [method OS.get_connected_midi_inputs].
+		[codeblocks]
+		[gdscript]
+		func _ready():
+		    OS.open_midi_inputs()
+		    print(OS.get_connected_midi_inputs())
+
+		func _input(input_event):
+		    if input_event is InputEventMIDI:
+		        _print_midi_info(input_event)
+
+		func _print_midi_info(midi_event: InputEventMIDI):
+		    print(midi_event)
+		    print("Channel " + str(midi_event.channel))
+		    print("Message " + str(midi_event.message))
+		    print("Pitch " + str(midi_event.pitch))
+		    print("Velocity " + str(midi_event.velocity))
+		    print("Instrument " + str(midi_event.instrument))
+		    print("Pressure " + str(midi_event.pressure))
+		    print("Controller number: " + str(midi_event.controller_number))
+		    print("Controller value: " + str(midi_event.controller_value))
+		[/gdscript]
+		[csharp]
+		public override void _Ready()
+		{
+		    OS.OpenMidiInputs();
+		    GD.Print(OS.GetConnectedMidiInputs());
+		}
+
+		public override void _Input(InputEvent inputEvent)
+		{
+		    if (inputEvent is InputEventMIDI midiEvent)
+		    {
+		        PrintMIDIInfo(midiEvent);
+		    }
+		}
+
+		private void PrintMIDIInfo(InputEventMIDI midiEvent)
+		{
+		    GD.Print(midiEvent);
+		    GD.Print("Channel " + midiEvent.Channel);
+		    GD.Print("Message " + midiEvent.Message);
+		    GD.Print("Pitch " + midiEvent.Pitch);
+		    GD.Print("Velocity " + midiEvent.Velocity);
+		    GD.Print("Instrument " + midiEvent.Instrument);
+		    GD.Print("Pressure " + midiEvent.Pressure);
+		    GD.Print("Controller number: " + midiEvent.ControllerNumber);
+		    GD.Print("Controller value: " + midiEvent.ControllerValue);
+		}
+		[/csharp]
+		[/codeblocks]
+		Note that Godot does not currently support MIDI output, so there is no way to emit MIDI signals from Godot. Only MIDI input works.
 	</description>
 	</description>
 	<tutorials>
 	<tutorials>
+		<link title="MIDI Message Status Byte List">https://www.midi.org/specifications-old/item/table-2-expanded-messages-list-status-bytes</link>
+		<link title="Wikipedia General MIDI Instrument List">https://en.wikipedia.org/wiki/General_MIDI#Program_change_events</link>
+		<link title="Wikipedia Piano Key Frequencies List">https://en.wikipedia.org/wiki/Piano_key_frequencies#List</link>
 	</tutorials>
 	</tutorials>
 	<members>
 	<members>
 		<member name="channel" type="int" setter="set_channel" getter="get_channel" default="0">
 		<member name="channel" type="int" setter="set_channel" getter="get_channel" default="0">
+			The MIDI channel of this input event. There are 16 channels, so this value ranges from 0 to 15. MIDI channel 9 is reserved for the use with percussion instruments, the rest of the channels are for non-percussion instruments.
 		</member>
 		</member>
 		<member name="controller_number" type="int" setter="set_controller_number" getter="get_controller_number" default="0">
 		<member name="controller_number" type="int" setter="set_controller_number" getter="get_controller_number" default="0">
+			If the message is [code]MIDI_MESSAGE_CONTROL_CHANGE[/code], this indicates the controller number, otherwise this is zero. Controllers include devices such as pedals and levers.
 		</member>
 		</member>
 		<member name="controller_value" type="int" setter="set_controller_value" getter="get_controller_value" default="0">
 		<member name="controller_value" type="int" setter="set_controller_value" getter="get_controller_value" default="0">
+			If the message is [code]MIDI_MESSAGE_CONTROL_CHANGE[/code], this indicates the controller value, otherwise this is zero. Controllers include devices such as pedals and levers.
 		</member>
 		</member>
 		<member name="instrument" type="int" setter="set_instrument" getter="get_instrument" default="0">
 		<member name="instrument" type="int" setter="set_instrument" getter="get_instrument" default="0">
+			The instrument of this input event. This value ranges from 0 to 127. Refer to the instrument list on the General MIDI wikipedia article to see a list of instruments, except that this value is 0-index, so subtract one from every number on that chart. A standard piano will have an instrument number of 0.
 		</member>
 		</member>
 		<member name="message" type="int" setter="set_message" getter="get_message" enum="MIDIMessage" default="0">
 		<member name="message" type="int" setter="set_message" getter="get_message" enum="MIDIMessage" default="0">
+			Returns a value indicating the type of message for this MIDI signal. This is a member of the MIDIMessage enum.
+			For MIDI messages between 0x80 and 0xEF, only the left half of the bits are returned as this value, as the other part is the channel (ex: 0x94 becomes 0x9). For MIDI messages from 0xF0 to 0xFF, the value is returned as-is.
+			Notes will return [code]MIDI_MESSAGE_NOTE_ON[/code] when activated, but they might not always return [code]MIDI_MESSAGE_NOTE_OFF[/code] when deactivated, therefore your code should treat the input as stopped if some period of time has passed.
+			For more information, see the MIDI message status byte list chart linked above.
 		</member>
 		</member>
 		<member name="pitch" type="int" setter="set_pitch" getter="get_pitch" default="0">
 		<member name="pitch" type="int" setter="set_pitch" getter="get_pitch" default="0">
+			The pitch index number of this MIDI signal. This value ranges from 0 to 127. On a piano, middle C is 60, and A440 is 69, see the "MIDI note" column of the piano key frequency chart on Wikipedia for more information.
 		</member>
 		</member>
 		<member name="pressure" type="int" setter="set_pressure" getter="get_pressure" default="0">
 		<member name="pressure" type="int" setter="set_pressure" getter="get_pressure" default="0">
+			The pressure of the MIDI signal. This value ranges from 0 to 127. For many devices, this value is always zero.
 		</member>
 		</member>
 		<member name="velocity" type="int" setter="set_velocity" getter="get_velocity" default="0">
 		<member name="velocity" type="int" setter="set_velocity" getter="get_velocity" default="0">
+			The velocity of the MIDI signal. This value ranges from 0 to 127. For a piano, this corresponds to how quickly the key was pressed, and is rarely above about 110 in practice.
 		</member>
 		</member>
 	</members>
 	</members>
 </class>
 </class>