Skip to content

Instantly share code, notes, and snippets.

@danferns
Created December 2, 2022 11:00
Show Gist options
  • Select an option

  • Save danferns/e2e53db7086824511e5a5fc4dfc036aa to your computer and use it in GitHub Desktop.

Select an option

Save danferns/e2e53db7086824511e5a5fc4dfc036aa to your computer and use it in GitHub Desktop.
Play Genshin Impact instruments with your MIDI Keyboard
# This script enables MIDI support for the musical instruments in
# Genshin Impact.
# It works by listening for MIDI messages, and then converting
# them into typing keystrokes based on a mapping between the
# musical notes and the computer keys.
# It bahaves like a normal computer keyboard, and so, this code
# can be modified to work with other games as well. All you need
# to do is create a mapping function for that game.
# IMPORTANT:
# The keystrokes don't get detected by the game unless this script
# is run with Administrator priviledges.
# Author: Daniel Fernandes
import pyautogui
import pydirectinput
import mido
# Logs the keystrokes sent
LOGGING = True
# Override default value to improve responsiveness
pydirectinput.PAUSE=0
# Mapping Function for GI Lyre
# You can also just create a dictionary of MIDI notes mapped
# to letters, instead of mapping them procedurally like this
keymap = "zxcvbnmasdfghjqwertyu"
whitekeys = [0, 2, 4, 5, 7, 9, 11]
def mapNoteToKey(note):
if (note % 12 in whitekeys):
octave = note // 12
root = whitekeys.index(note % 12)
keyindex = (root + len(whitekeys) * (octave - 4)) % len(keymap)
mappedKey = keymap[keyindex]
return mappedKey
def isNoteOn(msg):
return msg.type == 'note_on' and msg.velocity != 0
def isNoteOff(msg):
return msg.type == 'note_off' or (msg.type == 'note_on' and msg.velocity == 0)
inputPorts = mido.get_input_names()
if (len(inputPorts) == 0):
print("No MIDI inputs available. Please connect one and restart this script.")
exit()
# Uncomment the next three lines to list the names of all ports
# print("Available Input Ports: ")
# for port in inputPorts:
# print(port)
# Specify the port to connect to by passing its name to open_input()
# By default, it will connect to the first port listed to mido
with mido.open_input() as inport:
print("Listening to Input Port:", inport.name)
for msg in inport:
if isNoteOn(msg):
key = mapNoteToKey(msg.note)
if not key: continue
pydirectinput.keyDown(key)
if (LOGGING): print('Key Pressed:', key)
elif isNoteOff(msg):
key = mapNoteToKey(msg.note)
if not key: continue
pydirectinput.keyUp(key)
if (LOGGING): print('Key Released:', key)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment