From de9adcf04549ffa3d51271c166bafe03074bd3bb Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Mon, 27 Dec 2021 19:26:40 -0800 Subject: Document InputEventMIDI and add some missing 0xF MIDI messages --- core/core_constants.cpp | 11 +++++++ core/input/input_enums.h | 11 +++++++ doc/classes/@GlobalScope.xml | 47 +++++++++++++++++++++++----- doc/classes/InputEventMIDI.xml | 69 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 7 deletions(-) diff --git a/core/core_constants.cpp b/core/core_constants.cpp index e49c0a14fd..cd56233c58 100644 --- a/core/core_constants.cpp +++ b/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, CHANNEL_PRESSURE); 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 diff --git a/core/input/input_enums.h b/core/input/input_enums.h index 6b2dd2728e..aa55316ec8 100644 --- a/core/input/input_enums.h +++ b/core/input/input_enums.h @@ -95,6 +95,17 @@ enum class MIDIMessage { PROGRAM_CHANGE = 0xC, CHANNEL_PRESSURE = 0xD, 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 { diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index efd9b6e180..7f794fef6e 100644 --- a/doc/classes/@GlobalScope.xml +++ b/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. - MIDI note OFF message. + MIDI note OFF message. See the documentation of [InputEventMIDI] for information of how to use MIDI inputs. - MIDI note ON message. + MIDI note ON message. See the documentation of [InputEventMIDI] for information of how to use MIDI inputs. - MIDI aftertouch message. + MIDI aftertouch message. This message is most often sent by pressing down on the key after it "bottoms out". - 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. - MIDI program change message. + MIDI program change message. This message sent when the program patch number changes. - 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. - MIDI pitch bend message. + MIDI pitch bend message. This message is sent to indicate a change in the pitch bender (wheel or lever, typically). + + + MIDI system exclusive message. This has behavior exclusive to the device you're receiving input from. Getting this data is not implemented in Godot. + + + MIDI quarter frame message. Contains timing information that is used to synchronize MIDI devices. Getting this data is not implemented in Godot. + + + 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. + + + MIDI song select message. Specifies which sequence or song is to be played. Getting this data is not implemented in Godot. + + + MIDI tune request message. Upon receiving a tune request, all analog synthesizers should tune their oscillators. + + + MIDI timing clock message. Sent 24 times per quarter note when synchronization is required. + + + MIDI start message. Start the current sequence playing. This message will be followed with Timing Clocks. + + + MIDI continue message. Continue at the point the sequence was stopped. + + + MIDI stop message. Stop the current sequence. + + + MIDI active sensing message. This message is intended to be sent repeatedly to tell the receiver that a connection is alive. + + + MIDI system reset message. Reset all receivers in the system to power-up status. It should not be sent on power-up itself. 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. diff --git a/doc/classes/InputEventMIDI.xml b/doc/classes/InputEventMIDI.xml index 040eee7b98..1e41d09ac0 100644 --- a/doc/classes/InputEventMIDI.xml +++ b/doc/classes/InputEventMIDI.xml @@ -1,27 +1,96 @@ + Input event for MIDI inputs. + 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. + https://www.midi.org/specifications-old/item/table-2-expanded-messages-list-status-bytes + https://en.wikipedia.org/wiki/General_MIDI#Program_change_events + https://en.wikipedia.org/wiki/Piano_key_frequencies#List + 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. + 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. + 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. + 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. + 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. + 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. + The pressure of the MIDI signal. This value ranges from 0 to 127. For many devices, this value is always zero. + 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. -- cgit v1.2.3