diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0be2a57 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!midilyre-gen.py \ No newline at end of file diff --git a/midilyre-gen.py b/midilyre-gen.py new file mode 100644 index 0000000..9608604 --- /dev/null +++ b/midilyre-gen.py @@ -0,0 +1,57 @@ +import mido +import sys +import os + +keymap = ['z', ' ', 'x', ' ', 'c', 'v', ' ', 'b', ' ', 'n', ' ', 'm', 'a', ' ', 's', ' ', 'd', 'f', ' ', 'g', ' ', 'h', ' ', 'j', 'q', ' ', 'w', ' ', 'e', 'r', ' ', 't', ' ', 'y', ' ', 'u'] + +octave_range = (48, 84) #change to allow other ranges (within 0-127, see midi note numbers), range must be <=36 (3 octaves) +offset = 5 #transpose how many steps up or down (positive = higher); for shifting to C major to eliminate half notes +delay = 5000 #ms before arduino code runs for alt tabbing to genshin etc + +#genshin ignores SendInput without admin, since it runs elevated +#to work around this (and also most anticheat detection if any), +#this code does not play via pyautogui but generates arduino code for the macro instead, +#in order to play it directly as from an HID device instead of virtual keystrokes + +#midilyre-gen.py +#generates a simple 32u4 or SAMD micro based Arduino-compatible code file that performs the inputted midi on Genshin Impact's lyre via keystrokes. + +try: + mid_file = sys.argv[1] +except IndexError: + print('Please include the input file path as an argument!') + quit() + +mid = mido.MidiFile(mid_file) +print('Opening: ' + str(mid)) + +try: + os.mkdir('output') +except: + pass + +with open('output/' + mid.filename.rsplit('.', 1)[0] + '.ino', "w") as f: + f.write('#include \n\n') + f.write('void setup() {\n') + f.write(' Keyboard.begin();\n') + f.write(' delay(' + str(delay) + ');\n') + + for msg in mid: + if msg.type == 'key_signature': + print(str(msg)) + + if msg.type == 'note_on': + if msg.velocity != 0: #not muted + note = msg.note + offset + if note < octave_range[0] or note >= octave_range[1] or (note % 12) in [1, 3, 6, 8, 10]: #out of range and sharp not supported + print('Discarding unsupported note: ' + str(note)) + else: + f.write(' Keyboard.write(\'' + keymap[(note - octave_range[0])] + '\');\n') + + if msg.time != 0: #only include actual delays + f.write(' delay(' + str(msg.time * 1000) + ");\n") #mido.tick2second(msg.time, ticks_per_beat = mid.ticks_per_beat, tempo = current_tempo) needed if single track object + + f.write('}\n') + f.write('void loop() {}') + +print("Finished!") \ No newline at end of file